React useEffect引入函数依赖导致console.log重复打印问题求助
问题成因
- 你在App组件里定义的
randomFunc没有做缓存,每次App组件重新渲染时,都会生成一个全新的函数引用。 - 第一次进入Hello组件时,useEffect触发第一次执行
randomFunc,函数内部调用setData更新了App组件的状态,触发App组件重新渲染。 - App重渲染生成了新的
randomFunc引用,传递给Hello组件后,Hello组件的useEffect检测到依赖项randomFunc发生变化,就会第二次执行useEffect里的逻辑,所以console.log会打印两次。 - 如果直接把
randomFunc移出依赖数组,虽然只会执行一次,但不符合React Hook的依赖规则,就会抛出缺失依赖的警告。
解决方案
你可以用useCallback Hook缓存randomFunc的引用,保证只有依赖项变化的时候才会生成新的函数实例,修改后的App.js代码如下:
import { useState, useCallback } from "react"; import { Switch, Route, Link } from "react-router-dom"; import Home from "./Home"; import Hello from "./Hello"; export default function App() { const [data, setData] = useState(); // 用useCallback缓存函数,空依赖数组表示组件挂载时只生成一次函数引用 const randomFunc = useCallback((dataFromHelloComponent) => { setData(dataFromHelloComponent); console.log(dataFromHelloComponent); }, []); return ( <div className="App"> <Link to="/hello">Go to Hello!</Link> <Switch> <Route path="/" exact component={Home} /> <Route path="/hello" render={(props) => ( <Hello {...props} randomFunc={randomFunc} data={data} /> )} /> </Switch> </div> ); }
- 如果你后续
randomFunc内部需要用到App组件里的其他响应式变量,把对应的变量加到useCallback的依赖数组里即可。 - 这样修改后,Hello组件的useEffect依赖的
randomFunc引用不会因为App组件状态更新而变化,只会执行一次,也不会报依赖缺失的警告。
内容的提问来源于stack exchange,提问作者JustANewCoder
相关产品推荐
相关产品推荐

