最近在学习React,在useState部分被困扰了半天,分享一下问题!如下代码:
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`Count updated to ${count}`);
}, [count]);
const increment = () => {
setCount(count + 1);
};
const reset = () => {
setCount(0);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={reset}>Reset</button>
</div>
);
}
export default Counter;
流程解析
-
初始状态
count
为0
。- 页面显示
0
。 - 输出
Count updated to 0
。
-
状态值不同的情况
- 用户点击“Increment”按钮,调用
setCount(count + 1)
。 count
变为1
。- 页面显示
1
。 - 输出
Count updated to 1
。
- 用户点击“Increment”按钮,调用
-
状态值不同的情况
- 用户点击“Reset”按钮,调用
setCount(0)
。 count
变为0
。- 页面显示
0
(记作01
)。 - 输出
Count updated to 0
。
- 用户点击“Reset”按钮,调用
-
状态值相同的情况
- 用户再次点击“Reset”按钮,调用
setCount(0)
。 count
仍然是0
。- React 检查状态值是否相同(当前值为
0
,新值也是0
)。 - 由于值相同,React 不会触发实际的 DOM 更新。
- 但是,React 会执行一次“比较渲染”,确保状态的一致性。
- 输出
Count updated to 0
(记作02
)。
- 用户再次点击“Reset”按钮,调用
最终显示的值
- 最终状态值:最后一次调用
setCount(0)
后,状态值仍然是0
。 - 页面显示的值:页面显示的值是最后一次更新后的
0
(记作02
)。
总结
- 内存地址:尽管
01
和02
的内存地址不同,页面上显示的值仍然是0
。 - 实际渲染 vs. 比较渲染:当状态值相同但
setCount
被调用时,React 会执行一次“比较渲染”,确保状态的一致性,但不会实际更新 DOM。 - 页面显示:页面显示的值是最后一次更新后的
0
(记作02
)。
这个时候我的疑问出来了,明明01到02的变化是实实在在的替换,虽然是0 -->0的过程,但应该也算是重新渲染,为什么却叫做“比较渲染”。最后查了半天才发现是我钻牛角尖了。
从 01
到 02
的过程虽然涉及状态值的重新赋值,但由于值相同,React 不会触发实际的 DOM 更新。页面上的显示值仍然是 0
,只是内存地址不同。这种情况下不算实际的重新渲染。