const [counter, setCounter] = useState(0)
假设有两个异步函数func1和func2。这两个函数都是异步的,并更新计数器状态。Func1运行在func2之前
async function func1() {
....extra code
setCounter(counter + 1)
}
async function func2() {
....extra code
setCounter(counter + 1)
}
func1()
func2()
问题:
- 是否保证当func2的useState运行时,计数器的状态由func1更新?请记住这两个函数都是异步的。
- 如果没有,我应该做些什么来确保func2的use State只在func1的Usestate更新了Counter的值之后才运行。
在这里,func1和func2的使用状态都是将Counter加1。不管哪个函数先运行,输出都是一样的。但是,在回答"请回答"时,就好像两种状态执行不同的任务,为了达到预期的结果,func1应该在func2之前运行。
是否保证当
func2
的useState
运行时,计数器的状态由func1
更新?
不,一点也不。
如果没有,我应该做些什么来确保
func2
的使用状态只在func1
的Usestate
更新了计数器的值之后才运行。
你可以让func2
等待直到func1
返回的承诺(async
函数总是返回一个承诺),但是这并不一定意味着func2
在setCounter
状态更新发生之前没有开始运行;状态更新也是异步的。
func1
的承诺来解决和。使用setCounter
:setCounter(c => c + 1)
:
的回调形式async function func1() {
// ....extra code
setCounter(counter + 1);
}
async function func2() {
// ....extra code
setCounter(c => c + 1); // Note the callback form of state setter
}
func1().then(() => func2);
有很多种旋转方式。例如,您可以将func1
的promise作为参数传递给func2
,并在最后只设置await
:
基本思想是让func2
等待直到func1
完成。
async function func1() {
// ....extra code
setCounter(counter + 1);
}
async function func2(promise) {
// ....extra code
await promise; // Wait for `func1` to finish
setCounter(c => c + 1); // Note the callback form of state setter
}
func2(func1());
在绝大多数情况下,你可能并不关心func1
是否完成;只要在两个地方使用setCounter
的回调形式,这样它们都不会使用过时状态(它们关闭的counter
):
async function func1() {
// ....extra code
setCounter(c => c + 1);
}
async function func2() {
// ....extra code
setCounter(c => c + 1);
}
func1();
func2();
事实上,我认为任何当您使用现有状态(counter
的前一个值)来更新状态(将其加1)时,您应该使用setter的回调形式。关闭状态变量的旧副本真的很容易;使用回调表单可以确保您使用的是最新状态。
不能保证当func2运行时func1已经更新了状态。要在功能组件中实现这一点,你可以使用useEffect钩子来跟踪状态计数器:
的变化。useEffect(() => {
func2();
}, [counter])
通过这样做,每次计数器状态发生变化时都运行func2。另外,如果您想确保func1更新状态后func2只运行一次,您可以使用这样的标志:
const isStateUpdatedByFunc1 = useRef(false);
async function func1() {
....extra code
isStateUpdatedByFunc1.current = true;
setCounter(counter + 1);
}
useEffect(() => {
if(isStateUpdatedByFunc1.current){
isStateUpdatedByFunc1.current = false;
func2();
}
}, [counter])