useEffect
useEffect 让我们能够在下面四种时机去执行一个回调函数产生副作用:
1.每次 render 后执行:不提供第二个依赖项参数。比如useEffect(() => {})。
2.仅第一次 render 后执行:提供一个空数组作为依赖项。比如useEffect(() => {}, [])。
3.第一次以及依赖项发生变化后执行:提供依赖项数组。比如useEffect(() => {}, [deps])。
4.组件 unmount 后执行:返回一个回调函数。比如useEffect() => { return () => {} }, [])。
那么在定义依赖项时,我们需要注意以下三点:
1.依赖项中定义的变量一定是会在回调函数中用到的,否则声明依赖项其实是没有意义的。
2.依赖项一般是一个常量数组,而不是一个变量。因为一般在创建 callback 的时候,你其实非常清楚其中要用到哪些依赖项了。
3.React 会使用浅比较来对比依赖项是否发生了变化,所以要特别注意数组或者对象类型。如果你是每次创建一个新对象,即使和之前的值是等价的,也会被认为是依赖项发生了变化。这是一个刚开始使用 Hooks 时很容易导致 Bug 的地方。
bug示例:
function Sample() { // 这里在每次组件执行时创建了一个新数组 const todos = [{ text: 'Learn hooks.'}]; useEffect(() => { console.log('Todos changed.'); }, [todos]); }
代码的原意可能是在 todos 变化的时候去产生一些副作用,但是这里的 todos 变量是在函数内创建的,实际上每次都产生了一个新数组。所以在作为依赖项的时候进行引用的比较,实际上被认为是发生了变化的。