React useEffect依赖无变化仍触发?求原因及最佳实践
问题原因
React 中 useEffect 的设计逻辑是:组件首次挂载时一定会执行一次回调,依赖数组的作用仅用于控制组件后续重新渲染时,是否触发回调。哪怕依赖数组里的状态从未被修改,首次挂载的执行也是默认行为,这是为了支持初始化时的副作用操作(比如请求数据、绑定事件)。
优雅解决方案与最佳实践
方案1:用Ref标记首次挂载
通过 useRef 创建一个标记变量,记录是否是组件首次渲染,在 useEffect 中跳过首次执行的逻辑:
import React from 'react'; export function App(props) { const [testString, setTestString] = React.useState('abc'); // 标记是否为首次挂载 const isFirstMount = React.useRef(true); React.useEffect(() => { if (isFirstMount.current) { // 首次挂载时更新标记,不执行业务逻辑 isFirstMount.current = false; return; } // 仅当testString变化时才执行的逻辑 console.log('******* 只有state变化时才会触发!') }, [testString]); return ( <div className='App'> <h1>Hello React.</h1> <h2>Start editing to see some magic happen!</h2> </div> ); }
方案2:封装自定义Hook(最佳实践)
如果多个组件都需要这个逻辑,可以把判断首次挂载的逻辑封装成可复用的自定义Hook,提高代码复用性:
import React from 'react'; // 自定义Hook:仅在依赖变化时执行,跳过首次挂载 function useUpdateEffect(effect, dependencies) { const isFirstMount = React.useRef(true); React.useEffect(() => { if (isFirstMount.current) { isFirstMount.current = false; } else { return effect(); } }, dependencies); } export function App(props) { const [testString, setTestString] = React.useState('abc'); // 使用自定义Hook useUpdateEffect(() => { console.log('******* 只有state变化时才会触发!') }, [testString]); return ( <div className='App'> <h1>Hello React.</h1> <h2>Start editing to see some magic happen!</h2> </div> ); }
内容的提问来源于stack exchange,提问作者flyingbee
相关产品推荐
相关产品推荐

