我测试了一些代码,让我混淆了
有两个复制,
- 使用setState函数将State设置为相同的先前状态值
const [state, setState] = useState(1)
setState(() => 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"));