React useEffect依赖漏写,重复渲染!
·
💓 博客主页:瑕疵的CSDN主页
📝 Gitee主页:瑕疵的gitee主页
⏩ 文章专栏:《热点资讯》
昨天改个需求,组件突然像中了邪一样疯狂重渲染。控制台刷屏“useEffect执行”,UI卡得像PPT。我盯着代码,手抖得差点把咖啡泼在键盘上。
报错现场
function UserList() {
const [users, setUsers] = useState([]);
const fetchData = () => {
// 模拟API请求
setTimeout(() => setUsers([{ id: 1, name: '张三' }]), 500);
};
// 错误写法:依赖数组漏了fetchData
useEffect(() => {
fetchData();
}, []); // 你以为这里安全?大错特错!
return <div>{users.map(u => u.name)}</div>;
}
结果:每次状态变化(比如组件挂载后),fetchData都重新执行。数据重复请求,UI反复刷新。
核心根源
React的useEffect依赖数组是防抖开关。漏写依赖项,React会认为“每次渲染都有新数据”,强制重执行effect。
这里fetchData在effect内部定义,但依赖数组是空的。React不会跟踪fetchData的变化,所以每次渲染都当新函数处理。
对比代码
// 错误:依赖数组空,但用到了外部函数
useEffect(() => {
fetchData(); // 依赖了fetchData,但没写进数组
}, []); // 每次渲染都触发
// 正确:依赖数组包含所有外部变量
useEffect(() => {
fetchData(); // 依赖了fetchData
}, [fetchData]); // 必须加!
关键修复
把effect里用到的所有外部变量塞进依赖数组。这里fetchData是函数,必须显式声明:
// 修正后:依赖数组包含fetchData
useEffect(() => {
fetchData();
}, [fetchData]); // 拼命提醒自己:别漏!
避坑总结
- ESLint是救命稻草:装
eslint-plugin-react-hooks,exhaustive-deps规则会直接报错。
npm install eslint-plugin-react-hooks --save-dev
- 写effect前先问自己:
“这个effect里用了哪些外部变量?”(比如data、fetchData、userId)
一个不漏,全塞进数组。 - 空数组不是万能:
useEffect(() => {...}, [])只用于初始化请求(比如挂载时加载数据)。
如果用了data,必须写[data],否则重复请求。 临时方案别乱用:
有人写useEffect(() => {...}, [someVar])但someVar可能为undefined。
用useRef存函数:const fetchDataRef = useRef(fetchData); fetchDataRef.current = fetchData; // 保持最新 useEffect(() => { fetchDataRef.current(); }, []);
最后吐个槽:这依赖数组坑我三次了。昨天debug到三点,发现是漏了fetchData。别信“依赖数组空就安全”——React不骗人,它只是太诚实。下次写前,先在注释里写:
// 依赖:fetchData(别漏!)
记住:useEffect不是自动防抖,是手动防抖。你漏了,它就疯狂刷。
更多推荐

所有评论(0)