为什么useEffect回调拿不到最新state?如何让其获取当前状态值?
问题原因
这是React Hooks的闭包陷阱导致的:
你给useEffect传入了空依赖数组[],这个effect只会在组件首次挂载时执行一次,它返回的清理函数捕获的是首次渲染作用域下的initialValue和value,这两个值从effect创建时就被固定。后续组件重新渲染产生的新变量,这个老的清理函数无法访问,因此永远只能拿到初始值做比较。
修复方案
有两种简便的实现方式,不需要复杂逻辑:
方案1:用useRef存储变更标记(最稳妥,无额外执行开销)
通过useRef存储实时更新的变更状态,清理函数直接读取ref的current属性就能拿到最新结果:
const CustomInput = ({initialValue}) => { const [value, setValue] = useState(initialValue); // 存储value是否发生过变更的标记 const isValueChangedRef = useRef(false); // 每次value或initialValue更新时,同步修改变更标记 useEffect(() => { isValueChangedRef.current = value !== initialValue; }, [value, initialValue]); useEffect(() => { return () => { // 卸载时直接读取最新的变更标记即可 if (isValueChangedRef.current) { console.log('initial value changed'); // 执行你的自定义逻辑 } } }, []); }
方案2:直接存储最新的value和initialValue(适合后续需要用到最新值做其他处理的场景)
如果后续还要用到最新的value或initialValue做其他逻辑,可以直接把两个值存在ref里:
const CustomInput = ({initialValue}) => { const [value, setValue] = useState(initialValue); const latestValRef = useRef(value); const latestInitialValRef = useRef(initialValue); // 每次渲染同步更新ref的值 latestValRef.current = value; latestInitialValRef.current = initialValue; useEffect(() => { return () => { if (latestInitialValRef.current !== latestValRef.current) { console.log('initial value changed'); // 执行自定义逻辑 } } }, []); }
内容的提问来源于stack exchange,提问作者codego
相关产品推荐
相关产品推荐

