如何实现自定义Hook使异步setData后立即获取最新data值
实现可同步获取最新值的自定义useState Hook
React内置的useState状态更新是异步批量执行的,所以调用setter后直接读取state变量只能拿到旧值。要实现调用自定义setter后立即获取最新状态,可通过以下几种方案实现:
方案一:让setter函数返回最新状态
修改自定义Hook,让setValue在更新状态后直接返回最新值,这样在异步调用后可以直接拿到结果:
import { useState, useCallback } from 'react'; const useCustomState = (initialValue) => { const [value, setValue] = useState(initialValue); const customSetValue = useCallback((newValue) => { // 兼容函数式更新的场景 const updatedValue = typeof newValue === 'function' ? newValue(value) : newValue; setValue(updatedValue); return updatedValue; }, [value]); return [value, customSetValue]; }; // 使用示例 const [data, setData] = useCustomState(0); useEffect(() => { const fn = async () => { const newData = await setData(1); console.log(newData); // 输出 1 }; fn(); }, []);
方案二:用Ref同步状态,提供获取最新值的方法
通过Ref维护一份与状态同步的副本,同时暴露一个getter函数,随时可以获取最新值:
import { useState, useRef, useCallback, useEffect } from 'react'; const useCustomState = (initialValue) => { const [value, setValue] = useState(initialValue); const valueRef = useRef(value); // 组件更新时同步Ref与状态 useEffect(() => { valueRef.current = value; }, [value]); const customSetValue = useCallback((newValue) => { const updatedValue = typeof newValue === 'function' ? newValue(valueRef.current) : newValue; // 先更新Ref,保证同步获取 valueRef.current = updatedValue; setValue(updatedValue); }, []); const getCurrentValue = useCallback(() => valueRef.current, []); return [value, customSetValue, getCurrentValue]; }; // 使用示例 const [data, setData, getData] = useCustomState(0); useEffect(() => { const fn = async () => { await setData(1); console.log(getData()); // 输出 1 }; fn(); }, []);
方案三:直接暴露同步状态的Ref
如果不想额外封装getter函数,也可以直接返回Ref,通过ref.current直接访问最新值(注意不要直接修改ref.current,状态更新仍通过setter完成):
import { useState, useRef, useCallback, useEffect } from 'react'; const useCustomState = (initialValue) => { const [value, setValue] = useState(initialValue); const valueRef = useRef(value); useEffect(() => { valueRef.current = value; }, [value]); const customSetValue = useCallback((newValue) => { const updatedValue = typeof newValue === 'function' ? newValue(valueRef.current) : newValue; valueRef.current = updatedValue; setValue(updatedValue); }, []); return [value, customSetValue, valueRef]; }; // 使用示例 const [data, setData, dataRef] = useCustomState(0); useEffect(() => { const fn = async () => { await setData(1); console.log(dataRef.current); // 输出 1 }; fn(); }, []);
核心原理
React的useState状态更新会触发组件重新渲染,新状态要等到下一次渲染才会生效。而Ref的更新是同步的,通过在自定义Hook中用Ref维护一份与状态实时同步的副本,就能在调用setter后立即获取到最新值,无需等待组件重新渲染。
内容的提问来源于stack exchange,提问作者yakiler
相关产品推荐
相关产品推荐

