javascript 如果useEffect侦听一个非状态值,在依赖项数组中有一个非状态值会有什么影响?

ou6hu8tu  于 2022-10-30  发布在  Java
关注(0)|答案(3)|浏览(322)

每次Comp重新呈现时,rand将是不同的值。它会触发useEffect吗?

function Comp({}) {
  const rand = Math.random();

  useEffect(() => {
    // do stuff
  }, [rand])
}
xfb7svmp

xfb7svmp1#

任何变量都可以进入依赖数组,不管是不是state,只要它在数组中并且改变了,useEffect的回调函数就会被重新执行.
现在,useEffect是如何注意到这个变化的呢?嗯,每当组件呈现时,它都会执行diff。只有statesetState的变化才能触发呈现(这里不讨论呈现,因为这里有父组件呈现)。
如果你已经理解了这个机制,你可以停在这里,用React构建你的神奇产品:)。否则,继续阅读。我编了一个例子来解释更多。
假设我们有下面的组件。我们应该在组件第一次渲染时,以及每次rand更改时,在控制台中记录Hello Word。单击button会更改rand,但我们不会有新的日志,因为没有state更改时,没有任何重新渲染,所以useEffect没有做diff。所以它不知道这个变化。

export default function Comp() {
  let rand = Math.random();
  useEffect(() => {
    console.log("Hello Word");
  }, [rand]);
  return (
      <button onClick={() => { rand = Math.random() }}>
        New value
      </button>
  );
}

让我们对这个组件做一些修改,如下所示。现在每次点击按钮,组件都会重新呈现,因为我们用setState设置了state,在重新呈现时,如果rand的值与前一个值不同,我们将得到一个新的日志。

export default function Comp() {
  const [state, setState] = useState(true); // new line added
  let rand = Math.random();
  useEffect(() => {
    console.log("Hello Word");
  }, [rand]);
  // notice that the click handler has changed
  return (
      <button onClick={() => setState(!state)}>
        New value
      </button>
  );
}
x6h2sr28

x6h2sr282#

每次重新呈现组件时,都会计算Math.random方法,因此它将导致useEffect再次运行(rand已更改的情况除外)。
相反,如果它只是一个常量,它将不会重新运行useEffect

mm5n2pyu

mm5n2pyu3#

如果你在useEffect中使用console.log("hello"),你会发现你只看到两个控制台显示“hello”(因为componentWillMount和componentDidMount)。这意味着,你的组件只有在状态变量的值改变或者传递给它的属性改变时才会重新呈现(当然传递的属性必须是状态,否则它不会重新呈现)。
结论:只有组件中stateprops的值发生更改时,才会重新呈现组件。

相关问题