为什么反应状态(useState)在记录时更新但没有更新?

时间:2021-07-03 03:59:10

标签: javascript reactjs state

您好,我正在尝试创建一个简单的多文件组件,但文件状态未按预期运行。

FileUpload 组件工作正常,当用户选择一个文件并开始上传时,会调用 onStart 属性方法。然后当它成功完成时,'onFinish' prop 方法被调用。这段代码似乎很好,可以在 onfinish 方法中安慰对象。它在被 onStart Method 修改之前控制对象的旧值。我希望控制台中的文件对象值包含缓冲区键,因为它是在调用 onStart 方法时添加的,但它不存在。

示例初始状态文件应为 [] 当对状态文件调用使用效果时应将状态文件更新为 [{_id:"example_unique_id"}] 然后将出现一个上传按钮,当用户选择一个文件和 {{1 }} 修改对象,状态应该更新为 onStart,最后当它完成时 [{_id:"example_unique_id", buffer:{}] 应该是 files,但这里它返回 [{_id:"example_unique_id", buffer:{}]

我会错过什么?

此外,我已经安装了 React Dev 工具,并且似乎在开发工具中的状态更新得很好。

[{_id:"example_unique_id"}]

2 个答案:

答案 0 :(得分:0)

我认为问题是由于您的此代码未更新状态造成的:

  const addFile = (file, id) => {
  const old_object = files.filter((file) => file._id == id)[0];
    const index = files.indexOf(old_object);
    const new_files = [...files];
    new_files.splice(index, 1, { ...old_object, buffer: file });
    setFiles(new_files);
}

files 看起来像一个对象数组。 展开运算符不会对这个数组进行深拷贝。网上有很多例子,这里举一个。

let newArr = [{a : 1, b : 2},
             {x : 1, y : 2},
              {p: 1, q: 2}];

let arr = [...newArr];
arr[0]['a'] = 22;
console.log(arr);
console.log(newArr);

所以你的 new_files 是同一个数组。 Splice 必须进行一些修改,但已经到位。因此,当您执行此 setFiles(new_files); 时,您基本上设置了与 newState 相同的对象引用。 React 不会检测到更改,也不会更新任何内容。

您可以选择为您的特定 code 实施深层复制方法或使用 lodash cloneDeep。 查看您的代码,这可能对您有用:const new_files = JSON.parse(JSON.stringify(files))。它有点慢,您可能会丢失具有函数或符号等值的属性。 Read

答案 1 :(得分:0)

您得到旧日志的原因是closures

当您在 setFiles(new_files) 函数中执行 addFiles 时。 React 异步更新状态,但新状态在下一次渲染时可用。

将被调用的 onFinish 函数仍然来自第一次渲染,引用该渲染的 files。新渲染包含对更新文件的引用,因此下次您再次登录时,您将获得正确的值。

如果只是记录日志,请将其包裹在 useEffect 钩子中,

useEffect(() => {
  console.log(files)
}, [files);

如果是在 onFinish 处理程序中使用它,有 answers 可以探索这些选项。