先贴一个解决方法的原文链接:react useState 异步 数据获取不到 - 掘金
初学typescript,在React中遇到了useState异步更新的问题。
首先定了一个list,以及用来更新list的setMList函数
const [mList, setMList] = useState<number[]>([])
最开始我没有意识到异步的问题,直接使用setMList方法进行更新,并继续后续的逻辑。然后我发现mList并没有更新,最开始我只认为是删除指定元素的代码写错了,但debug后发现只是setMList“没有成功运行”。
//mList=[1,12,123,1234,123456....]
setMList(produce(mList, draft => {
const index = draft.findIndex(c => c === 123456);
if (index !== -1) {
draft.splice(index, 1);
}
}))
console.log(mList)
//mList=[1,12,123,1234,123456....]
这主要是因为useState在React中是异步更新的问题,用同步的写法只能靠撞大运。作为初学者,我选择使用一个中间变量的方式,让console.log变得同步。参考转载文章的方法三。
方法一 : 利用
ref
- 官网中的一段话:如果你刻意地想要从某些异步回调中读取最新的 state,你可以用 一个 ref 来保存它,修改它,并从中读取
-
const App = () => { const [arr, setArr] = useState([0]); let ref = useRef(); useEffect(() => { ref.current = arr; console.log(arr); }); const handleClick = () => { Promise.resolve().then(() => { const now = [...ref.current, 1]; ref.current = now; setArr(now); }) .then(() => { setArr([...ref.current, 2]); }); } return ( <button onClick={handleClick}>change</button> ); }
方法二 :使用(回调)方式传参
const handleClick = () => {
Promise.resolve().then(() => {
setArr(prevState => [...prevState, 1]); // 这里也可以不改,使用 setArr([...arr, 1])
}).then(() => {
setArr(prevState => [...prevState, 2]); // 这里必须改成回调函数传参方式,否则会读取旧状态,导致异常
});
}
方法三 : 处理办法添加一个 副作用(
useEffect()
)
- 异步获取数据存在的问题, 我这里通过useEffect用存储2次, 没办法 ,解决问题就行了,其他的也不重要
-
const [categtry, setCategtry] = useState([]); const [categData, setCategData] = useState([]); useEffect(() => { getCollaCategory(); }, []); useEffect(() => { // 这个useEffect很关键,第一次赋值但是获取不到,所以要再赋值一次 if (categtry) { setCategData(categtry); } }, [categtry]); const getCollaCategory = async () => { const { resp } = await call(service.getCollaCategory); if (resp.Code === 0) { // 第一次虽然在这里赋值了,但是外部想拿到 categtry这个变量还是空的 setCategtry(resp.CategoryTree.SubCategoryList); } }