React中如何在自定义Hook卸载时将状态保存到Context?
解决组件卸载时将状态保存到Context的自定义Hook问题
原代码的核心问题在于卸载时执行的useEffect清理函数存在闭包陷阱:
- 依赖数组为空,导致清理函数捕获的是初始渲染时的上下文值,若
key参数变化或setStateStore出现不稳定情况(虽然useState返回的更新函数通常稳定),会导致更新Context的操作失效 - 虽用
stateRef跟踪了最新状态,但缺少必要依赖的清理函数无法保证执行时的上下文环境正确
修改后的自定义Hook代码
function useSpecialState(defaultValue, key) { const { stateStore, setStateStore } = useContext(StateStoreContext); // 函数式初始化,避免每次渲染重复执行状态判断 const [state, setState] = useState(() => { return stateStore[key] !== undefined ? stateStore[key] : defaultValue; }); const stateRef = useRef(state); // 同步最新状态到ref,确保卸载时能获取当前值 useEffect(() => { stateRef.current = state; }, [state]); // 卸载时保存状态到Context,添加必要依赖避免闭包问题 useEffect(() => { return () => { setStateStore((prevStateStore) => ({ ...prevStateStore, [key]: stateRef.current, })); }; }, [setStateStore, key]); // 加入稳定的setStateStore和参数key作为依赖 return [state, setState]; }
修改说明
- 函数式初始化优化:将
useState的初始值改为函数形式,避免组件每次渲染都执行stateStore[key]的判断逻辑,提升性能 - 修复闭包问题:给卸载逻辑的
useEffect添加setStateStore和key作为依赖:setStateStore是useState返回的更新函数,本身始终稳定,不会触发额外的清理函数重建key作为Hook的入参,确保清理函数使用的是当前组件对应的最新key值
- 保留按需保存逻辑:仅在组件卸载时执行Context更新,不会在每次状态变更时触发多余操作
额外修复提示
父组件StateStoreComponent中存在拼写错误:props. Children应改为props.children(小写c),否则无法正确渲染子元素。
内容的提问来源于stack exchange,提问作者Laczkó Örs
相关产品推荐
相关产品推荐

