React setState后读取本地state得到undefined/旧值,如何用async/await或promise解决
问题根源
React 中 useState 的更新方法是批量异步执行的,更新操作不会立即修改当前函数作用域内捕获的 state 变量,同时 setState 本身也不返回 Promise 对象,因此直接用 async/await 等待更新没有效果。
你在调用 setCurrentNodef 后立刻打印的 currentNodef,始终是本次渲染闭包拿到的旧值,所以会出现首次打印undefined、后续点击打印上一次值的现象。
实现方案
方案1:使用 useEffect 监听 state 变化(官方推荐)
如果需要在 state 更新完成后执行后续逻辑,最符合 React 设计规范的方式是通过 useEffect 监听对应 state 的变更:
// 原state定义不变 const [currentNodef, setCurrentNodef] = React.useState(); // 新增监听逻辑 React.useEffect(() => { // state更新后会自动触发这里的逻辑,拿到的是最新值 console.log(currentNodef); // 你要执行的后续逻辑(比如打开弹窗等)写在这里 }, [currentNodef]); // 点击函数不需要额外改动 const openModalUpdateNode= (rowInfo)=>{ const { node, treeIndex, path } = rowInfo; setCurrentNodef(node); }
方案2:封装支持 Promise 的 useState 满足 async/await 需求
如果一定要用 async/await 或者 .then 的写法实现,可以自定义封装支持 Promise 的 useState hook:
// 自定义hook const useStateWithPromise = (initialValue) => { const [state, setState] = React.useState(initialValue); const setStateAsync = React.useCallback((newValue) => { return new Promise((resolve) => { setState(prevState => { const nextState = typeof newValue === 'function' ? newValue(prevState) : newValue; resolve(nextState); return nextState; }); }); }, []); return [state, setStateAsync]; }; // 使用自定义hook替换原有useState const [currentNodef, setCurrentNodef] = useStateWithPromise(); // 点击函数使用async/await写法 const openModalUpdateNode = async (rowInfo) => { const { node, treeIndex, path } = rowInfo; const newNode = await setCurrentNodef(node); // 这里可以直接拿到返回的最新值,不需要读取作用域内的currentNodef console.log(newNode); }
简化方案
如果你的后续逻辑只需要用到最新的 node 值,不需要依赖 state 更新后的其他副作用,完全可以直接使用传入的 node 变量,不需要等待 state 更新:
const openModalUpdateNode= (rowInfo)=>{ const { node, treeIndex, path } = rowInfo; setCurrentNodef(node); console.log(node); // 直接使用即可,不需要读state }
内容的提问来源于stack exchange,提问作者Thomazzz
相关产品推荐
相关产品推荐

