这里的大多数答案都是关于如何根据其先前的值更新状态,但我不明白这与问题有何关系
useState set 方法没有立即反映更改
反应18
useState 是异步的:
当触发某个代码的事件发生时,代码开始运行,当它完成时,react将检查是否有状态更新,如果是,则只有useState
更新钩子的值,这会导致一个新的渲染,其中新值可用。
const [example,setExemple] = useState("")
//...
<button
onClick={() => {
const newValue = "new";
setExample(newValue);
console.log(example); // output "" and this is normal, because the component didn't rerenderd yet so the new value is not availabe yet
}}
>
Update state
</button>
假设我们有一个场景,其中一个状态依赖于另一个状态,例如我们希望根据example
每次更新时的新值进行 API 调用,然后将响应中的数据存储在另一个状态中anotherExample
。
为了实现这样我们有两种方法:
**1. 使用 的值newValue
:
**
<button
onClick={async () => {
const newValue = "new";
const response = await axios.get(`http://127.0.0.1:5000/${newValue}`);
setExample(newValue);
setAnotherExample(response.data);
}}
>
test
</button>
因为您知道example
将收到该值,所以您可以直接基于它创建逻辑。
2.每次更新时触发useEffect运行,方法是将其包含在其依赖项数组中:example``example
<button
onClick={() => {
const newValue = "new";
setExample(newValue);
}}
>
test
</button>
useEffect(() => {
async function test(){
const response = await axios.get(`http://127.0.0.1:5000/${example}`);
setAnotherExample(response.data);
}
test();
}, [example])
因此,当example
使用事件函数更新组件重新渲染时,我们现在处于一个新的不同渲染中,一旦完成,useEffect
就会运行**,因为 的值example
与上次渲染期间的值不同**,并且因为它是一个新的不同渲染, useState 挂钩的新值example
可在此处获得。
注意:useEffect
在第一次安装期间,钩子无论如何都会运行。
哪种方法更好?
-
而第一种方法将使所有工作在一次渲染中完成**(更好的方法)** “React 将多个状态更新分组到单个重新渲染中以获得更好的性能”,第二种方法将在两次渲染中完成,第一次example
更新时和第二个anotherExample
是从内部更新的useEffect
😕
-
由于组件仅在useState
钩子的新值与旧值不同时才重新渲染,因此当newValue
等于 时example
组件不会重新渲染,因此useEffect
不会运行且anotherExample
不会更新 🙂 (更好的方法),但是在第一个中无论如何,API 都会被调用,如果没有必要,我们不想这样做,如果发生这种情况,anotherExample
也会更新(anotherExample
将收到它已经包含的相同数据,因为它是相同的请求,因为newValue
等于example
)但是如果然后,在对象或数组中响应,Object.is
方法(钩子useState
使用的)无法检测新值是否等于前一个值,因此,组件将重新渲染😕
结论:
正如上面提到的,每种都有其优点,所以这取决于用例。
更推荐使用第二种方法,但是在某些情况下,第一种方法的性能更高,例如,当您确定代码仅在newValue
使用 获取新值时才会运行onChange
,或者当您想使用您将要使用的其他一些局部变量时不再能够从 useEffect 内部访问