React Native中useCallback内useState状态无法更新问题求助
解决React Native中useCallback无法获取useState最新状态的问题
问题核心
你的useCallback回调捕获了初始的bar值,后续通过useEffect更新bar时,回调内的bar不会同步更新;且runFirstFunction触发的bar更新是异步执行的,导致当前foo回调执行时无法拿到最新的bar值。
方案1:用useRef跟踪最新状态(侵入性最小)
不需要大幅修改现有代码,通过useRef保存最新的bar值,避免闭包捕获旧值:
export const Foo = <T>(props): <T> => { const value = undefined; // 假设实际为props传入值 const [bar, setBar] = useState<boolean>(false); // 定义ref保存最新bar值 const barRef = useRef<boolean>(bar); // 每次bar更新时同步ref useEffect(() => { barRef.current = bar; }, [bar]); useEffect(() => { pipe( value, O.fromNullable, O.fold( () => setBar(false), () => setBar(true) ), ); }, [value]); const foo = useCallback(() => { runFirstFunction(); pipe( barRef.current, // 取最新的bar值 B.fold( () => falseFunction(), () => trueFunction(), ), ); restOfFooFunctionality(); }, [setBar]); // 依赖保持不变,避免回调频繁重建 };
方案2:同步更新bar并直接使用(逻辑允许时)
如果runFirstFunction执行后可以直接确定bar的新值,把setBar逻辑移到foo内,直接使用计算后的新值,无需等待异步的useEffect更新:
export const Foo = <T>(props): <T> => { const value = undefined; const [bar, setBar] = useState<boolean>(false); useEffect(() => { pipe( value, O.fromNullable, O.fold( () => setBar(false), () => setBar(true) ), ); }, [value]); const foo = useCallback(() => { runFirstFunction(); // 直接计算bar的新值(和useEffect内逻辑一致) const newBar = value != null; setBar(newBar); pipe( newBar, // 直接使用刚计算的新值 B.fold( () => falseFunction(), () => trueFunction(), ), ); restOfFooFunctionality(); }, [setBar, value]); };
方案3:用useReducer统一管理复杂状态逻辑
如果状态依赖关系复杂,useReducer可以避免闭包问题,把状态更新和业务逻辑统一放到reducer中:
type FooState = { bar: boolean }; type FooAction = | { type: 'UPDATE_BAR_FROM_VALUE', value: unknown } | { type: 'RUN_FOO' }; const fooReducer = (state: FooState, action: FooAction): FooState => { switch (action.type) { case 'UPDATE_BAR_FROM_VALUE': return { ...state, bar: action.value != null }; case 'RUN_FOO': runFirstFunction(); // 这里可以直接获取最新状态,或者计算新的bar值 const newBar = /* 根据实际逻辑计算 */; // 直接执行对应逻辑 newBar ? trueFunction() : falseFunction(); restOfFooFunctionality(); return { ...state, bar: newBar }; default: return state; } }; export const Foo = <T>(props): <T> => { const value = undefined; const [state, dispatch] = useReducer(fooReducer, { bar: false }); useEffect(() => { dispatch({ type: 'UPDATE_BAR_FROM_VALUE', value }); }, [value]); const foo = useCallback(() => { dispatch({ type: 'RUN_FOO' }); }, []); };
内容的提问来源于stack exchange,提问作者Wayne Filmater
相关产品推荐
相关产品推荐

