useState异步解决方法
React 的 useState是异步更新状态的,但是当需要在状态更新后立即执行一些操作,有以下几种解决方法:
- 使用
useEffect
来监听状态的变化,并在其中执行操作:
const [state, setState] = useState(initialState);
useEffect(() => {
// 在这里执行操作
}, [state]);
- 在使用 setState 时传入回调函数:【注意:官方已移除setState的回调,此法不通】
setState(prevState => {
// 更新状态
return newState;
}, () => {
// 在回调函数中执行操作
});
可使用setState(prevState=>prevState+1
)来在原数据基础上修改
- 使用
useRef
来保存变量并在 useEffect 中使用:
const [state, setState] = useState(initialState);
const isUpdating = useRef(false);
useEffect(() => {
if (isUpdating.current) {
// 在这里执行操作
isUpdating.current = false;
}
}, [state]);
//页面
<div>
<Button onClick={()=>{setState(newValue)}></Button>
</div>
4.Promise实现回调:
const [count, setCount] = useState(0);
const addCount = () => {
new Promise((resolve) => {
setCount((num) => {
resolve(num + 1);
return num + 1;
});
}).then(newValue => {
console.log(newValue);
//...newValue即为最新的count值
});
};
<button onClick={addCount}>+1</button>
多次set数据则是:
const [arr, setArr] = useState([0]);
useEffect(() => {
console.log(arr);
}, [arr]);
const handleClick = () => {
Promise.resolve().then(() => {
setArr(prevState => [...prevState, 1]); // 这里也可使用setArr([...arr, 1]); 因为这里不需要获取最新状态
})
.then(() => {
setArr(prevState => [...prevState, 2]); // 这里必须改成回调函数传参方式,否则会读取旧状态,导致异常
});
}
1. return (
1. <>
1. <button onClick={handleClick}>change</button>
1. </>
1. );
1.
5.useSyncCallback方法【codesandbox可查看demo】:
import { useEffect, useState, useCallback } from "react";
const useSyncCallback = (callback) => {
const [proxyState, setProxyState] = useState({ current: false });
const Func = useCallback(() => {
setProxyState({ current: true });
}, [proxyState]);
useEffect(() => {
if (proxyState.current === true) setProxyState({ current: false });
}, [proxyState]);
useEffect(() => {
proxyState.current && callback();
});
return Func;
};
export default useSyncCallback;
import { useState } from "react";
import useSyncCallback from "./fn";
export default () => {
const [state, setstate] = useState(0);
/** 将func的方法传递给useSyncCallback然后返回一个新的函数 */
const func = useSyncCallback(() => {
console.log(state);
});
const setT = () => {
setstate(prev=>prev+1);
func();
};
return (
<div className="App">
<button onClick={setT}>+1</button>
</div>
);
};