reactjs - 使用 React useEffect、useState 和 setInterval 将秒数添加到 Intl.dateTimeFormat
问题描述
我遇到了一个奇怪的问题,在 setState() 钩子函数中更改克隆的顺序会改变预期的行为。
我试图每秒增加一秒的值。然而,这样做会直接导致秒数增加 2 而不是 1。
这有效
const [value, setValue] = useState(new Date());
useEffect(() => {
const interval = setInterval(
() =>
setValue((value) => {
const clonedDate = new Date(value.getTime());
clonedDate.setSeconds(clonedDate.getSeconds() + 1); // Add one second to the time
return clonedDate;
}),
1000
);
return () => {
clearInterval(interval);
};
}, []);
这增加了两秒而不是一秒
const [value, setValue] = useState(new Date());
useEffect(() => {
const interval = setInterval(
() =>
setValue((value) => {
value.setSeconds(value.getSeconds() + 1);
const clonedDate = new Date(value.getTime());
return clonedDate;
}),
1000
);
return () => {
clearInterval(interval);
};
}, []);
解决方案
我唯一清楚的是,在第二个版本中,状态突变显然正在发生,但老实说,我不清楚确切的位置。似乎即使您正在创建一个新的javascriptDate
对象,它仍然在引用前一个数据对象的属性。
考虑以下表现出相同行为的示例:
function App() {
const [value1, setValue1] = useState({ c: 0 });
const [value2, setValue2] = useState({ c: 0 });
useEffect(() => {
const interval = setInterval(
() =>
setValue1((value) => {
const clonedValue = { ...value }; // shallow copy first
clonedValue.c = clonedValue.c + 1; // update copy
return clonedValue; // return copy
}),
1000
);
return () => {
clearInterval(interval);
};
}, []);
useEffect(() => {
const interval = setInterval(
() =>
setValue2((value) => {
value.c = value.c + 1; // mutate current
const clonedValue = { ...value }; // shallow copy
return clonedValue; // return copy
}),
1000
);
return () => {
clearInterval(interval);
};
}, []);
return (
<div className="App">
<h1>Non-mutaiton Version</h1>
{value1.c}
<h1>Mutation Version</h1>
{value2.c}
</div>
);
}
不过有趣的是,如果您React.StrictMode
从两者中删除 ,App
则两者的性能相同。
StrictMode 目前有助于:
- 识别具有不安全生命周期的组件
- 关于旧版字符串引用 API 使用的警告
- 关于不推荐使用 findDOMNode 的警告
- 检测意外的副作用
- 检测遗留上下文 API
严格模式不能自动为您检测副作用,但它可以通过使它们更具确定性来帮助您发现它们。这是通过有意双重调用以下函数来完成的:
- 类组件
constructor
,render
和shouldComponentUpdate
方法 - 类组件静态
getDerivedStateFromProps
方法 - 功能组件体
- 状态更新函数(setState 的第一个参数)
- 传递给
useState
、useMemo
或的函数useReducer
使用在 StrictMode 和非 StrictMode 下运行的原始日期对象进行演示:
推荐阅读
- python-3.x - 无法在 cmd 中将 pip 版本 10.0.1 升级到 18.0
- php - 创建 JSON 文件并显示
- interrupt - 启用外部中断时 STM32L4R5xx 挂起
- git - 返回两次提交,但将最后两次保留在新分支中
- vba - 使用 VBA 进行递归树状解析
- android - MVVMCROSS Xamarin.Android 6.1.2 库导航
- spring-integration - Spring集成jdbc数组更新查询spel表达式
- wpf - WPF 为路径添加自定义工具提示
- java - 如何在 java 中解析 /getusereffectivepermissions 共享点响应?
- javascript - 如何将 setInterval 定位到特定的 html 标记