Javascript 涉及先前状态的计算何时需要功能更新?

Javascript 涉及先前状态的计算何时需要功能更新?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,根据useStateReact钩子的: 如果使用以前的状态计算新状态,则可以传递 函数设置状态。函数将接收上一个值, 并返回更新后的值 如此给定 const [count, setCount] = useState(initialCount); 你可以写 setCount(prevCount => prevCount + 1); 我理解将updater函数表单与setState一起使用的原因,因为多个调用可能是批处理的。然而 在随后的重新呈现过程中,useState 将始终是应用更新后

根据
useState
React钩子的:

如果使用以前的状态计算新状态,则可以传递 函数设置状态。函数将接收上一个值, 并返回更新后的值

如此给定

const [count, setCount] = useState(initialCount);
你可以写

setCount(prevCount => prevCount + 1);
我理解将updater函数表单与
setState
一起使用的原因,因为多个调用可能是批处理的。然而

在随后的重新呈现过程中,
useState
将始终是应用更新后的最新状态

所以我不清楚为什么上面的例子不能写成

setCount(count + 1);
(这就是它在中的呈现方式)

是否存在必须使用
useState
钩子的功能更新才能获得正确结果的情况


(编辑:可能与相关)

仍然需要函数更新语法的主要场景是在异步代码中。想象一下,在
useffect
中,您执行了某种API调用,当调用完成时,您更新了一些状态,这些状态也可以通过其他方式进行更改<代码>使用效果将在效果开始时关闭状态值,这意味着在API调用完成时,状态可能已过期

下面的示例通过单击按钮触发两个在不同时间完成的不同异步进程来模拟此场景。一个按钮立即更新计数;一个按钮在不同的时间触发两个异步增量,而不使用函数更新语法(Naive按钮);最后一个按钮使用函数更新语法(健壮按钮)在不同时间触发两个异步增量

您可以在CodeSandbox中使用它来查看效果

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function App() {
  const [count, setCount] = useState(1);
  const [triggerAsyncIndex, setTriggerAsyncIndex] = useState(1);
  const [triggerRobustAsyncIndex, setTriggerRobustAsyncIndex] = useState(1);
  useEffect(
    () => {
      if (triggerAsyncIndex > 1) {
        setTimeout(() => setCount(count + 1), 500);
      }
    },
    [triggerAsyncIndex]
  );
  useEffect(
    () => {
      if (triggerAsyncIndex > 1) {
        setTimeout(() => setCount(count + 1), 1000);
      }
    },
    [triggerAsyncIndex]
  );
  useEffect(
    () => {
      if (triggerRobustAsyncIndex > 1) {
        setTimeout(() => setCount(prev => prev + 1), 500);
      }
    },
    [triggerRobustAsyncIndex]
  );
  useEffect(
    () => {
      if (triggerRobustAsyncIndex > 1) {
        setTimeout(() => setCount(prev => prev + 1), 1000);
      }
    },
    [triggerRobustAsyncIndex]
  );
  return (
    <div className="App">
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <br />
      <button onClick={() => setTriggerAsyncIndex(triggerAsyncIndex + 1)}>
        Increment Count Twice Async Naive
      </button>
      <br />
      <button
        onClick={() => setTriggerRobustAsyncIndex(triggerRobustAsyncIndex + 1)}
      >
        Increment Count Twice Async Robust
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

import React,{useState,useffect}来自“React”;
从“react dom”导入react dom;
函数App(){
const[count,setCount]=useState(1);
const[triggerAsyncIndex,setTriggerAsyncIndex]=useState(1);
常量[triggerRobustAsyncIndex,setTriggerRobustAsyncIndex]=useState(1);
使用效果(
() => {
如果(triggerAsyncIndex>1){
setTimeout(()=>setCount(count+1),500);
}
},
[triggerAsyncIndex]
);
使用效果(
() => {
如果(triggerAsyncIndex>1){
setTimeout(()=>setCount(count+1),1000);
}
},
[triggerAsyncIndex]
);
使用效果(
() => {
如果(triggerRobustAsyncIndex>1){
setTimeout(()=>setCount(prev=>prev+1),500);
}
},
[triggerRobustAsyncIndex]
);
使用效果(
() => {
如果(triggerRobustAsyncIndex>1){
setTimeout(()=>setCount(prev=>prev+1),1000);
}
},
[triggerRobustAsyncIndex]
);
返回(
计数:{Count}
setCount(计数+1)}>增量计数

setTriggerAsyncIndex(triggerAsyncIndex+1)}> 增量计数两次异步初始化
setTriggerRobustAsyncIndex(triggerRobustAsyncIndex+1)} > 两次递增计数异步健壮 ); } const rootElement=document.getElementById(“根”); ReactDOM.render(


另一种可能需要功能更新的场景是,如果多个效果正在更新状态(即使是同步的)。一旦一个效果更新了状态,另一个效果将看到过时的状态。这种场景对我来说似乎不太可能(在大多数情况下似乎是一个糟糕的设计选择)非常感谢!旁注-在您的示例中,“增量计数两次异步健壮”按钮仅在第一次单击时有效(除非您随后单击“增量计数两次异步幼稚”)。我认为第49行应该是
setTriggerRobustAsyncIndex(triggerRobustAsyncIndex+1)