useCallback+setState:两种写法的差异与正确性分析
React中useCallback两种写法的差异与有效性分析
方案正确性
两种方案都能正确实现点击温度按钮让温度值+1的需求,不存在功能错误。
核心差异对比
1. 依赖逻辑与引用稳定性
- 方案一:
useCallback(() => setTemp(temp+1), [temp])- 依赖数组包含
temp,每次temp更新时,useCallback会生成全新的函数引用。 - 当
seconds变化触发App组件重渲染时,只要temp没改变,useCallback就会复用之前缓存的函数引用,increaseTemp的引用保持不变。
- 依赖数组包含
- 方案二:
useCallback(() => setTemp(temp => temp+1), [])- 依赖数组为空,
useCallback会始终返回同一个函数引用,完全不受temp变化的影响。 - 这里用了
setState的函数式更新,直接基于当前最新的状态值计算新值,不需要依赖外部的temp变量,从根源上避免了对状态的依赖。
- 依赖数组为空,
2. 对组件重渲染的影响
由于TempDisplay用了React.memo,只有当props发生变化时才会触发重渲染:
- 点击「Increase by 10 seconds」按钮时:
- 方案一中,
temp未变化,increaseTemp引用也不变,TempDisplay的两个props都无改动,不会触发重渲染,满足要求。 - 方案二中,
increaseTemp引用全程稳定,temp也没变化,同样不会触发TempDisplay重渲染,满足要求。
- 方案一中,
- 点击温度按钮时:
- 两种方案都会因为
temp更新,导致TempDisplay的tempprops变化,触发重渲染(这是合理的,因为需要更新温度显示)。
- 两种方案都会因为
方案选择建议
方案二更值得推荐:它不需要依赖temp,函数引用完全稳定,不会因为状态更新反复创建新函数,写法也更简洁,符合React中「当新状态依赖旧状态时,优先使用函数式更新」的最佳实践。
方案一也能正常工作,但每次temp变化都会生成新的函数引用——虽然此时TempDisplay本来就要因为temp变化重渲染,不会产生额外性能问题,但相比方案二不够高效和简洁。
内容的提问来源于stack exchange,提问作者Roman2021
相关产品推荐
相关产品推荐

