我在升级react版本时发现了一个奇怪的现象:当将react从16.8.6升级到17.0.1时,新应用程序吞噬了一些日志消息,尽管在网页上呈现的结果仍然完全相同。有人能帮我解释一下吗?
详细说明:
这是我的组件:
let componentCount = 0;
let returnCount = 0;
let useSelectorCount = 0;
let useEffectCount = 0;
const Comp04ClickButtonPage = (): JSX.Element => {
componentCount++;
console.log(`[${componentCount}] component - START ----------------------`);
// useSelector
const stringValueState = useSelector((rootState: RootState): string => {
useSelectorCount++;
console.log(`[${componentCount}] selectorCount: ${useSelectorCount}`);
const result = rootState.comp04ClickButtonSlice.stringValue;
return result;
});
console.log(`[${componentCount}] component - after useSelectorCount`);
// useEffect
const dispatch = useDispatch();
useEffect(() => {
useEffectCount++;
console.log(`[${componentCount}] effectCount: ${useEffectCount}.`);
dispatch(thunkComp04ClickButton(`${new Date().getTime()}`));
}, [dispatch]);
console.log(`[${componentCount}] component - after useEffect`);
const onClickButton = () => {
componentCount = returnCount = useSelectorCount = useEffectCount = 0; // reset counts
console.log(`[${componentCount}] onClickNewValue`);
dispatch(thunkComp04ClickButton(`Random ${new Date().getTime()}`));
};
// render
returnCount++;
return (
<div>
{console.log(`[${componentCount}] renderCount: ${returnCount}`)}
<div>
[{componentCount}], useEffect: {useEffectCount}, useSelectorCount: {useSelectorCount}, returnCount: {returnCount}
</div>
<button onClick={onClickButton}>Click Button</button>
</div>
);
};
export default Comp04ClickButtonPage;
摘自旧版package.json
:
"dependencies": {
"@reduxjs/toolkit": "^1.5.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-intl": "^5.10.2",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.1",
"react-use": "^15.3.4",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.8",
"typescript": "^4.1.3",
"web-vitals": "^1.1.0"
}
新版本package.json
节选:
"dependencies": {
"@reduxjs/toolkit": "^1.5.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-intl": "^5.10.16",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.1",
"react-use": "^15.3.8",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.8",
"typescript": "^4.1.3",
"web-vitals": "^1.1.0"
}
旧版本日志:截图1
新版本日志:截图2
在新版本的截图中更具体:
失踪1:componentCount由"[1]
"改为"[2]
",实际日志信息为:
[1] renderCount: 1
[2] selectorCount: 2
但是如果我们看一下代码:
const Comp04ClickButtonPage = (): JSX.Element => {
componentCount++;
console.log(`[${componentCount}] component - START ----------------------`);
因此,期望的日志消息是:
[1] renderCount: 1
[2] component - START ----------------------
[2] selectorCount: 2
我不明白componentCount
是如何增加的,但component - START
日志信息缺失??
失踪2:在新版本的日志消息中(截图2),组件第四次执行时的整个日志丢失了(而它们在旧版本中出现了-截图1):
[4] component - START ----------------------
[4] selectorCount: 7
[4] component - after useSelectorCount
[4] component - after useEffect
[4] renderCount: 4
期望是这些日志消息应该在新React版本运行时以与旧版本相同的方式出现。
注意:网页的结果仍然是[4], useEffect: 1, useSelectorCount: 7, returnCount: 4
。这意味着执行componentCount++
行,而不打印下一行console.log([${componentCount}] component - START ----------------------);
的日志消息。这怎么可能呢?
p/S:完整代码:https://github.com/khoitnm/practice-react-redux
在该存储库中,有两个项目pro-00-old-react-version
和pro-01-redux-simple
。唯一的区别是package.json
文件。所有其他文件都是完全相同的。
Strictmode在开发过程中运行时将运行hooks/渲染多次以检测内存泄漏,这就是为什么您的组件在严格模式下渲染4次而不是2次。
我确实克隆了你的repo,发现了一些有趣的东西。在不改变log
的情况下console.log(`[${componentCount}] selectorCount: ${useSelectorCount}`);
从1跳转到3,值2不被记录。对于Chrome或React开发者来说,这可能是一个有趣的案例。虽然控制台日志没有显示,但控制台日志肯定是执行的,因为useSelectorCount++
与日志位于同一代码块中。当不使用严格模式时,所有这些都会消失。
对于不移除严格模式;如果你看一下stack overflow,你会发现严格模式是一个完美的脚枪,我相信开发者会为它感到骄傲,不会建议删除它,但如果你想学习React并预测组件何时渲染和钩子何时执行,那么使用它会让你感到困惑。