当状态改变和状态不变时,useState是如何真正工作的



我测试了一些代码,让我混淆了

有两个复制,

  1. 使用setState函数将State设置为相同的先前状态值
const [state, setState] = useState(1)
setState(() => 1)
  1. 使用setState函数将State设置为相同的值(总是相同的ex:1,true,其他(,但初始状态不同
const [state, setState] = useState(1)
setState(() => 2)

这是再现样本1

总是将状态设置为相同的值

首先打开codesandbox控制台并将其清除。

发生了什么

点击,状态已为1,setState功能将状态设置为1,

组件功能不重新运行

// console show 
test 
test
test

这是再现样本2

将状态设置为特定值

我总是将state设置为2。

第一次点击,状态从1变为2,因此组件功能重新运行

// console
test
app

第二次点击,状态已经是2,但为什么组件功能仍然重新运行

// console 
test 
app   <--------------  here component function re-run

第三次点击,状态已为2,组件功能不重新运行

// console 
test 

问题就在这里

在示例2中,第二次单击按钮,状态与以前,但仍在重新运行组件。

我们回到样本1和样本2中的第三次点击,这两个状态的改变步骤与样本2的第二次点击相同,与之前的状态相比,它们都是相同的设置相同的状态,但它们的输出方式不同

正如我所知,状态更改将导致组件功能重新运行。

我所期望的是样本2秒点击,组件功能不会重新运行

让我们只关注Simple 2,因为Simple 1流是开发人员所期望的。

简单的2个日志如下:

1. app  // first render
2. test // button click, log from the callback 
3. app  // state change from '1' to '2', second render
4. test // second button click
5. app  // no state change, why the log?
6. test // 3rd button click
7. test // 4th button click etc.

所以主要的问题是为什么会有第五个"应用程序"日志。其背后的原因隐藏在React文档中的某个地方,即退出状态更新:

请注意,React可能仍需要再次渲染该特定组件在跳伞之前。这不应该是一个问题,因为React不会不必要地深入树中。

简单地说,这只是一种边缘情况,React需要另一个渲染周期,但它没有进入Nodes树(即,它没有运行return语句,在您的示例中,它是React.FFragment<></>(

一个更具体的例子是;A":

const App = () => {
const [state, setState] = React.useState(0);
useEffect(() => {
console.log("B");
});
console.log("A");
return (
<>
<h1>{state}</h1>
<button onClick={() => setState(42)}>Click</button>
</>
);
};
ReactDOM.render(<App />, document.getElementById("root"));

最新更新