React组件挂载时useEffect依赖缺失问题的正确解决方案是什么
React useEffect仅挂载执行一次的合规解决方案
核心实现思路
针对仅需在组件挂载时执行一次的异步请求逻辑,可通过以下两种生产环境验证过的方案实现,既规避重复执行问题,也符合代码规范要求:
方案1:全量依赖加执行标记(完全符合ESLint规则,优先推荐)
前置依赖处理:
reduxDispatch:React Redux ≥7.1.0版本中,useDispatch返回的函数引用永久稳定,加入依赖数组不会触发useEffect重复执行subscription:将订阅创建逻辑完全移入useEffect内部,消除外部依赖- 可变状态判断:通过
useRef创建永久稳定的执行标记,控制业务逻辑仅跑一次
代码示例:
const DevicesMain = () => { console.log("Devices Main render") const [state, dispatch] = useReducer(reducer, initialState) const [sites, rooms, devices] = useSelector((state) => [state.sites, state.rooms, state.devices]) const reduxDispatch = useDispatch() // 执行标记,引用永久稳定 const hasExecuted = useRef(false) useEffect(() => { if (!hasExecuted.current) { hasExecuted.current = true console.log("did mount") if (!sites.get) { reduxDispatch(siteActions.getALL()) } if (!rooms.get) { reduxDispatch(roomActions.getALL()) } reduxDispatch(deviceActions.getALLWithIncludeCount()) // 订阅逻辑移到useEffect内部,无需作为外部依赖 const subscription = /* 原订阅创建逻辑 */ return () => { console.log("will unmount") subscription?.unsubscribe() } } // 所有外部依赖正常传入,有执行标记控制不会重复执行业务逻辑 }, [reduxDispatch, sites.get, rooms.get]) return <>{/* 组件渲染逻辑 */}</> }
方案2:指定规则禁用校验(团队规范允许时使用)
如果确认业务逻辑确实仅需执行一次,不需要响应任何依赖变化,可直接明确禁用exhaustive-deps规则,注意必须指定规则名避免误禁用其他校验:
useEffect(() => { // 业务逻辑和清理逻辑 }, []) // eslint-disable-next-line react-hooks/exhaustive-deps
该写法代码更简洁,是目前行业内模拟componentDidMount的常用实现方式,只要明确业务逻辑无依赖更新需求即可安全使用。
内容的提问来源于stack exchange,提问作者forevereffort
相关产品推荐
相关产品推荐

