前言
只有当依赖关系被改变时,useEffect hook 才会触发回调函数。而且它使用浅比较法来比较 hooks 的值。
1、依赖项是函数
import './App.css';
import { useEffect, useState } from 'react';
function App() {
const [num,setNum] = useState(0);
var mark1 = function () {
return "100";
}; // 唯一的对象引用
useEffect(()=>{
console.log("useEffect");
},[mark1]) // render每次更新都会执行,这个依赖无意义
return (
<div>
<header>
<button onClick={()=>setNum(num+1)}>点击我改变</button>
</header>
</div>
);
}
export default App;
报错警告: The ‘mark1’ function makes the dependencies of useEffect Hook (at line 14) change on every render. Move it inside the useEffect callback. Alternatively, wrap the definition of ‘mark1’ in its own useCallback() Hook react-hooks/exhaustive-deps
- 由于 useEffect 使用浅层比较法来比较数值。该函数的浅层比较将总是给出 false
如何改进?用useCallback
- useCallback 返回一个memoized 版本的回调,只在依赖关系改变时才会改变。
import { useCallback, useEffect, useState } from 'react';
function App() {
const [num,setNum] = useState(0);
var mark1 = useCallback(()=> {
return "100";
},[]);
useEffect(()=>{
console.log("useEffect");
},[mark1])
return (
<div>
<header>
<button onClick={()=>setNum(num+1)}>点击我改变</button>
</header>
</div>
);
}
export default App;
2、依赖项是数组
import { useEffect, useState } from 'react';
function App() {
const [num,setNum] = useState(0);
var dep = ['a']
useEffect(()=>{
console.log("useEffect");
},[dep]) // 依赖项在每次渲染时都发生变化
return (
<div>
<header>
<button onClick={()=>setNum(num+1)}>点击我改变</button>
</header>
</div>
);
}
export default App;
警告: The ‘dep’ array makes the dependencies of useEffect Hook (at line 11) change on every render. Move it inside the useEffect callback. Alternatively, wrap the initialization of ‘dep’ in its own useMemo() Hook react-hooks/exhaustive-dep
- 两个数组的浅层比较总是假的,所以 useEffect 总是会触发回调
[]===[] 的结果为false
如何解决?useRef
useRef 返回一个可变的对象,.current 具有初始值
import { useEffect, useRef, useState } from 'react';
function App() {
const [num,setNum] = useState(0);
// var dep = ['a'];
const dep2 = useRef(['a']);
useEffect(()=>{
console.log("useEffect");
},[dep2.current]) //
return (
<div>
<header>
<button onClick={()=>setNum(num+1)}>点击我改变</button>
</header>
</div>
);
}
export default App;
3、将对象作为依赖
{}==={}为false
对象的浅层比较将永远是假的,所以它将触发 useEffect 的回调。
如果修复这个问题?用useMemo 的 hook
如果我们将依赖关系备忘化,我们就能打破无限循环。
- useMemo 只有在依赖关系发生变化时才会重新计算记忆化的值。
import { useEffect, useMemo, useRef, useState } from 'react';
export default function App() {
const [count, setCount] = useState(0);
const data = useMemo(
() => ({
is_fetched: false,
}),
[]
); // <- dependencies
useEffect(() => {
setCount(count + 1);
}, [data]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={() => setCount(count + 1)}>{count}</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
参考来自:https://zhuanlan.zhihu.com/p/412283445