My App

在挂载时运行

在挂载时运行

这是视频中的沙盒。取消Effect中的注释以吸引你的注意力:

import React from 'react';

function App() {
  const [searchTerm, setSearchTerm] = React.useState('');

  const inputRef = React.useRef();

  React.useEffect(() => {
    // Uncomment me!
    // inputRef.current.focus();
  }, []);

  return (
    <>
      <header>
        <img
          className="logo"
          alt="Foobar"
          src="https://sandpack-bundler.vercel.app/img/foogle.svg"
        />
      </header>
      <main>
        <form>
          <input
            ref={inputRef}
            value={searchTerm}
            onChange={(event) => {
              setSearchTerm(event.target.value);
            }}
          />
          <button>Search</button>
        </form>
      </main>
    </>
  );
}

export default App;

“autofocus” 属性

HTML 表单输入具有一个 autofocus 属性,可以在页面加载时自动聚焦该元素:

<input autofocus type="text" />

鉴于有内置的方法可以自动聚焦输入,为什么我们还要为 useRef 和 useEffect 而费这么大劲呢?

不幸的是,在 React 中使用 autofocus 属性并不安全。

autofocus 属性只有在页面首次加载时元素存在的情况下才能可靠地工作。如果元素在之后动态注入到页面中,则无法正常工作。

在 React 中,几乎每个元素都是动态注入的!唯一的例外是如果你使用服务器端渲染,即便如此,也仅限于用户访问你网站的第一个页面。

因此,上述解决方案,通过引用捕获输入并触发 .focus() 在Effect中,是解决 React 中此问题的最佳方式。

订阅

假设我们想要跟踪用户的光标位置。每当他们移动鼠标时,我们将更新一些状态。

我们可以将 onMouseMove 事件处理程序添加到特定的 DOM 节点,如下所示:

<div
  onMouseMove={event => {
    setMousePosition({
      x: event.clientX,
      y: event.clientY,
    });
  }}
>

这仅在用户悬停在这个特定的 <div> 上时有效……如果我们想要跟踪他们的光标位置,无论鼠标在视口内的哪个位置呢?

如果你愿意,可以花几分钟时间进行尝试,看看能否找到解决方案。已经提供了一个沙盒:

为了监听全局事件,您可以使用 window.addEventListener 。有关更多信息,请查看 JavaScript 入门中的“全局事件”课程 👀 。

import React from 'react';

function MouseCoords() {
  const [
    mousePosition,
    setMousePosition
  ] = React.useState({ x: 0, y: 0 });
  
  return (
    <div className="wrapper">
      <p>
        {mousePosition.x} / {mousePosition.y}
      </p>
    </div>
  );
}

export default MouseCoords;

我们来讨论一下:

以下是视频中的图表:

带有空依赖数组:

effect-subscription-first-render

没有依赖数组:

effect-subscription-every-render

这是视频中的最终解决方案:

import React from 'react';

function MouseCoords() {
  const [mousePosition, setMousePosition] = React.useState({
    x: 0,
    y: 0,
  });

  React.useEffect(() => {
    function handleMouseMove(event) {
      setMousePosition({
        x: event.clientX,
        y: event.clientY,
      });
    }

    window.addEventListener('mousemove', handleMouseMove);
  }, []);

  return (
    <div className="wrapper">
      <p>
        {mousePosition.x} / {mousePosition.y}
      </p>
    </div>
  );
}

export default MouseCoords;

缺少清理!

在我上面的解决方案中,我添加了一个事件监听器,但我从未移除该事件监听器。这是一个问题——它可能导致内存泄漏和其他问题。

很快,我们将看到如何清理我们的订阅。请在完成该课程之前,不要在您的实际项目中应用这些模式!

On this page