纯函数是否需加入React Hooks useEffect依赖数组?
问题解答
核心结论
不管是不是纯函数,只要在useEffect回调里用到了外部值,就必须加入依赖数组——哪怕你觉得它“永不变化”,只要React无法确定其引用不会改变,就不能省略。官方文档的要求没有例外情况。
你的示例问题分析
你当前的代码存在隐藏风险:
- 父组件每次重渲染时,
handleNameChange都会被重新创建,导致子组件接收的onChangeprop是全新的函数引用。 - 子组件的
useEffect依赖只有state,所以当父组件重渲染导致onChange变化时,useEffect不会重新执行。这会引发逻辑不一致:比如父组件重渲染后,子组件的state没变化,但onChange已经更新成新函数了,此时如果state一直不变,最新的onChange永远不会被调用;如果后续state变化,虽然会调用新的onChange,但中间这段时间的逻辑是断层的。
为什么移到事件处理函数能正常运行
事件处理函数是在触发时才执行的,会直接使用当前最新的onChange prop,不存在“捕获旧变量快照”的问题。但useEffect是在组件挂载或依赖变化时执行的,它捕获的是执行瞬间的变量引用,依赖不全就会导致用旧值执行逻辑。
修复方案
要解决这个问题,需要确保onChange的引用稳定,同时补全useEffect的依赖:
- 父组件用
useCallback包裹函数,确保引用不变:
function ParentComponent({addressItems}) { // 根据setSomething内部用到的变量添加依赖,比如用到addressItems就加进去 const setSomething = useCallback(something => { // push something in browser address bar }, []) const handleNameChange = useCallback(name => { setSomething(name) }, [setSomething]) return <> <ChildComponent onChange={handleNameChange}/> </> }
- 子组件补全
useEffect的依赖数组:
function ChildComponent({onChange}) { const [state, setState] = useState('state') useEffect(() => { onChange(state) }, [state, onChange]) return <h1 onClick={_ => setState('newState')}> something </h1> }
这样不管父组件何时重渲染,只要handleNameChange的引用发生变化(比如它的依赖更新),子组件的useEffect都会重新执行,保证调用的是最新的onChange函数。
内容的提问来源于stack exchange,提问作者hamid-beigi
相关产品推荐
相关产品推荐

