【问题标题】:Should I use useEffect() for dom manipulation or just do it directly?我应该使用 useEffect() 进行 dom 操作还是直接进行操作?
【发布时间】:2020-09-15 14:09:31
【问题描述】:

React docs I see this piece of code

function Example() {
  const [count, setCount] = useState(0);

  //THE SUBJECT OF MY QUESTION:
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

所以,我的问题是为什么不使用 useEffect 更改 document.title 或任何其他 DOM,如下所示:

function Example() {
  const [count, setCount] = useState(0);

  //THE SUBJECT OF MY QUESTION:
  document.title = `You clicked ${count} times`;

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

我知道,例如发送请求时,它是异步的,我们需要在 useEffect 中进行。但是 DOM 操作不是异步的,它需要相对 0 的时间,为什么我们还要使用 useEffect 钩子呢?

【问题讨论】:

  • useEffect 没有第二个参数 ([]) 每次状态变化时都会渲染,所以在我看来它是一样的

标签: reactjs


【解决方案1】:

您最好将 DOM 操作和其他副作用保留在 useEffect 中。

useEffect(() => {
    document.title = `You clicked ${count} times`;
}, [count]); // set your dependencies

原因是:这种方法符合React Strict Mode 和即将推出的Concurrent Mode

什么并发模式is

[...] React 可能会在提交之前调用render阶段生命周期不止一次,或者它可能在根本不提交的情况下调用它们(因为错误或更高优先级的中断)。

在您的情况下,document.title 分配可能会重复多次,或者 React 甚至可能决定中止整个提交。一般来说,这会导致不一致:

因为上述方法可能会被多次调用,所以重要的是它们包含副作用。忽略此规则会导致各种问题,包括内存泄漏和无效的应用程序状态。 (docs)

【讨论】:

    【解决方案2】:

    几乎相同,请参阅我的相关答案,useEffect in-depth

    不同之处在于一个显着的“陷阱”,useEffect 回调执行 after the render phase

    const App = () => {
      useEffect(() => {
        console.log("executed after render phase");
      });
    
      console.log("executed at render phase");
    
      return <></>;
    };
    

    结果:

    executed at render phase
    executed after render phase
    

    【讨论】:

      【解决方案3】:

      了解useEffect 的工作原理很重要。

      这里有一些明确性。

      useEffect(() => {
        // this runs when the component mounts
      
        return () => {
          // This runs when the component unmounts (not useful for you right now)
        }
      }, []); // You were missing the second argument (dependencies array)
      

      关于dependencies 数组。将值放入其中将导致您的效果在该值更改时再次运行,这对您的需求非常有用。

      你应该做的是:

      useEffect(() => {
        document.title = `You clicked ${count} times`;
      }, [count]);
      

      这将在count 更改时更新document.title

      我通常建议在这类情况下使用useEffect,而不是简单地使用它,因为它会考虑所有生命周期过程。

      TLDR:它应该表现更好。

      【讨论】:

      • 他询问了文档中的示例:reactjs.org/docs/hooks-effect.html
      • 我明白了,我仍然坚持我的回答。不使用useEffect 意味着document.title 将在每次其他任何更改时重置。我相信依赖数组是useEffect钩子中非常重要的一部分,不应该被忽略。
      • 它不会被忽视...它是一个初学者指南,当您阅读时会解释它,您的答案在页面末尾...reactjs.org/docs/…
      猜你喜欢
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 2021-11-06
      • 1970-01-01
      • 2013-01-03
      • 2012-02-16
      相关资源
      最近更新 更多