javascript - 从多个组件同时写入单个状态对象
问题描述
在我的 create-react-app 应用程序中,我使用 App.js 中的 useState 挂钩创建了一个对象,我将其作为参数传递给同一组件的 5 个不同实例。这个对象在简单的数字属性名称下包含 5 个不同的数组(因此它们很容易使用 for 循环进行迭代)。
const [ listObj, setListObj ] = useState({ 0: [], 1: [], 2: [], 3: [], 4: [] });
每个组件维护和修改其中一个且只有一个数组(对应于它的编号,因此组件 0 仅修改组件 0,1 仅修改 1 等),并且我使用函数来迭代 listObj 和里面的数组,这样我就可以比较它们的内容。
这些组件每个都有一个通过 App.js 传递给它们的唯一 componentNumber (0-4),以及一个 useEffect 钩子,每当它们想要更新其特定数组时,每个组件看起来都像这样:
useEffect(() => {
let newArray = functionToGenerateSortedArrays();
let newListObj = { ...listObj, [ componentNumber ]: newArray };
setListObj( newListObj );
}, [ (all my state objects that trigger useEffect) ])
当我一次只更新与一个组件有关的内容时,这非常有用。问题是应用程序中有一个功能需要同时更新所有组件。似乎每个人都会获取 listObj 的“旧”副本,使用它来创建具有更新信息的 newListObj,然后使用 newListObj 调用 setListObj,从而覆盖其他组件尝试进行的更改。唯一正确更新的 listObj 数组是该行中的最后一个。
当我尝试实现这个 hacky 解决方案时,我认为自己非常聪明:
useEffect(() => {
let newArray = functionToGenerateSortedArrays();
setTimeout(() => {
let newListObj = { ...listObj, [ componentNumber ]: newArray };
setListObj( newListObj );
}, componentNumber * 100 );
}, [ (all my state objects that trigger useEffect) ])
但是,这不起作用。它实际上将 listObj 中的数组立即切换回我想要的值,但在超时触发后它恢复为错误的值。我不知道为什么,但如果有人有任何见解,我很想理解它。我认为这可能与 React 如何“批量”更新状态有关,但找不到任何关于如何阻止 React 这样做的信息,因此我可以测试我的假设。
我是否有任何选项可以以“级联”方式更改 listObj 中的数组值,以免它们相互干扰?是否有另一种不会产生此问题的保存和更新状态的方法?非常感谢你花时间陪伴。
解决方案
这是我们钩子设置器的状态更新回调形式的地方:useState
useEffect(() => {
let newArray = functionToGenerateSortedArrays();
setListObj(currentListObj => {
// ^^^^^^^^^^^^^^
let newListObj = { ...currentListObj, [ componentNumber ]: newArray };
return newListObj;
});
}, [ (all my state objects that trigger useEffect) ])
这样,即使将所有更新函数批处理在一起,它们也将接收当前值,而不是使用效果函数已关闭的过时值。
推荐阅读
- r - Grep 并根据这些值创建新的数据框
- python - 合并文本分类的多种统计方法,从 SVM 多类分类器开始
- asp.net-mvc - MVC:Ajax.ActionLink 是否可以使用图像和图像右侧的文本?
- vba - 如何在代码中将数组函数与数组一起使用
- java - 获取 java.io.IOException:服务器返回 HTTP 响应代码:400
- copy-paste - MobaXterm 鼠标右键双击
- r - 使用 rvest 从 ballotpedia.org 抓取表格数据
- c# - 在执行 select 子句之前检查列是否存在
- java - 扩展 JFrame 创建新的 JFrame 对象
- javascript - 在本机反应中使用 map() 列出数组元素