Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么在异步函数中状态值只计算一次?_Javascript_Reactjs_Use Effect - Fatal编程技术网

Javascript 为什么在异步函数中状态值只计算一次?

Javascript 为什么在异步函数中状态值只计算一次?,javascript,reactjs,use-effect,Javascript,Reactjs,Use Effect,如果调用类似于setCount(count+1)的代码是非同步的,为什么count的值只计算一次? 当您按两次Async Naive递增计数按钮时,它会触发两次超时,一次延迟500毫秒,另一次延迟1000毫秒。因此,我认为由于第一次超时通过setCount(count+1)触发重新渲染,count的值应该在第二次超时中更新?因为500毫秒是执行操作的充足时间,重新渲染应该会导致在调用第二个超时函数时更新计数 如果将函数传递给setCount,则第二个按钮Increment Count tweep

如果调用类似于
setCount(count+1)
的代码是非同步的,为什么count的值只计算一次?
当您按两次Async Naive递增计数按钮时,它会触发两次超时,一次延迟500毫秒,另一次延迟1000毫秒。因此,我认为由于第一次
超时
通过
setCount(count+1)
触发重新渲染,count的值应该在第二次
超时
中更新?因为500毫秒是执行操作的充足时间,重新渲染应该会导致在调用第二个
超时
函数时更新
计数

如果将函数传递给
setCount
,则第二个按钮
Increment Count tweep Async Robust
可以正常工作。所以如果count是1,它就变成了3。为什么在调用时评估的状态与前一个按钮不同

useffect(()=>{
如果(triggerAsyncIndex>1){
设置超时(()=>{
设置计数(计数+1);
}, 500);
}
},[triggerAsyncIndex]);
useffect(()=>{
如果(triggerAsyncIndex>1){
设置超时(()=>{
设置计数(计数+1);
}, 1000);
}
},[triggerAsyncIndex]);
useffect(()=>{
如果(triggerRobustAsyncIndex>1){
设置超时(
() =>
设置计数(上一个=>{
返回prev+1;
}),
500
);
}
},[triggerRobustAsyncIndex]);
useffect(()=>{
如果(triggerRobustAsyncIndex>1){
设置超时(
() =>
设置计数(上一个=>{
返回prev+1;
}),
1000
);
}
},[triggerRobustAsyncIndex]);
返回(
计数:{Count}
setCount(计数+1)}>增量计数

setTriggerAsyncIndex(triggerAsyncIndex+1)}> 增量计数两次异步初始化
setTriggerRobustAsyncIndex(triggerRobustAsyncIndex+1)} > 两次递增计数异步健壮 );
}
功能组件中的状态更新不仅是异步的,而且是由闭包绑定的,如果使用setTimeout,它们仍然会引用定义函数的值,这并不重要

由于以下useEffect函数仅在
triggerAsyncIndex
更改时重新触发,计数状态更新不会导致更新的值反映在第二个useEffect中,因为它在计数更新之前已经创建

  useEffect(() => {
    if (triggerAsyncIndex > 1) {
      setTimeout(() => {
        setCount(count + 1);
      }, 500);
    }
  }, [triggerAsyncIndex]);
  useEffect(() => {
    if (triggerAsyncIndex > 1) {
      setTimeout(() => {
        setCount(count + 1);
      }, 1000);
    }
  }, [triggerAsyncIndex]);
它需要重新呈现,以便在函数闭包中刷新计数值。旧的函数调用仍将保留以前的闭包值


这种情况下的想法是使用函数状态更新,如
setCount(prev=>prev+1)

函数组件中的状态更新不仅是异步的,而且是由闭包绑定的,如果使用setTimeout也无所谓,它们仍然会引用定义函数的值

由于以下useEffect函数仅在
triggerAsyncIndex
更改时重新触发,计数状态更新不会导致更新的值反映在第二个useEffect中,因为它在计数更新之前已经创建

  useEffect(() => {
    if (triggerAsyncIndex > 1) {
      setTimeout(() => {
        setCount(count + 1);
      }, 500);
    }
  }, [triggerAsyncIndex]);
  useEffect(() => {
    if (triggerAsyncIndex > 1) {
      setTimeout(() => {
        setCount(count + 1);
      }, 1000);
    }
  }, [triggerAsyncIndex]);
它需要重新呈现,以便在函数闭包中刷新计数值。旧的函数调用仍将保留以前的闭包值


这种情况下的想法是使用函数状态更新,如
setCount(prev=>prev+1)

我明白了。因此,由于[triggerAsyncIndex]没有改变,第二个setTimeout触发器所在的环境(包括count的值)仍然是相同的。那么为什么传递(prev=>prev+1)会更新它,因为它不会触发重新渲染,因为[triggerAsyncIndex]未更改?这是因为react确保它在内部将更新的值传递给setState调用。这也不受闭包的影响,因为这些值是从函数回调参数而不是从封闭的作用域接收的。因此,您可以将react视为另一个内部闭包,它保存更新的状态并像(prev=>prev+1)使React有机会传递更新的值。因此,与每次关闭一样,它自己的腔室也被及时锁定。更改该腔室的唯一方法是重新创建(重新运行)它或访问包含当前文件室的更新文件室,对吗?除了您建议的两种方法之外,还有另一种方法。您可以在useEffect中将状态复制到ref,并且由于refs对变异有效,更新的值将在我看到的函数中看到。因此,由于[triggerAsyncIndex]没有更改,环境(包括count的值),其中第二个setTimeout触发器仍然是相同的。那么为什么passing(prev=>prev+1)会更新它,因为它不会触发重新呈现,因为[triggerAsyncIndex]未更改?这是因为react确保它在内部将更新的值传递给setState调用。这也不受闭包的影响,因为这些值是从函数回调参数而不是从封闭的作用域接收的。因此,您可以将react视为另一个内部闭包,它保存更新的状态并像(prev=>prev+1)使React有机会传递更新的值。因此,与每次关闭一样,它自己的腔室也被及时锁定。更改该腔室的唯一方法是重新创建(重新运行)它或访问包含当前文件室的更新文件室,对吗?除了您建议的两种方法之外,还有另一种方法。您可以在useEffect中将状态复制到ref,并且由于refs对变异有效,更新后的值将在函数中看到