簡體   English   中英

為什么反應狀態(useState)在記錄時更新但沒有更新?

[英]Why react state (useState) is updated but not updated when log it?

您好,我正在嘗試創建一個簡單的多文件組件,但文件狀態未按預期運行。

FileUpload 組件工作正常,當用戶選擇一個文件並開始上傳時, onStart prop 方法被調用。 然后當它成功完成時,'onFinish' prop 方法被調用。 這段代碼似乎很好,可以在onfinish方法中安慰對象。 它在被onStart Method修改之前控制對象的舊值。 我希望控制台中的文件對象值包含緩沖區鍵,因為它是在onStart方法時添加的,但它不存在。

示例初始狀態文件應為[]當對狀態文件調用使用效果時應將狀態文件更新為[{_id:"example_unique_id"}]然后將出現一個上傳按鈕,當用戶選擇一個文件和onStart修改對象和狀態應該更新為[{_id:"example_unique_id", buffer:{}]最后當它完成files應該是[{_id:"example_unique_id", buffer:{}]但這里它返回[{_id:"example_unique_id"}]

我會錯過什么?

另外,我安裝了 React Dev 工具,並且似乎在開發工具中狀態更新得很好。

import React, { useState } from 'react'
import { useEffect } from 'react';
import unique_id from 'uniqid'
import FileUpload from "./../../components/FileUpload";

const InlineFileUpload = ({ onFilesChange }) => {
  const [files, setFiles] = useState([]);

  function onFinish(file, id) {
    const old_object = files.filter((file) => file._id == id)[0];
    console.log("old object on after upload", old_object);
  }

  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);
  };

  useEffect(() => {
    const new_attachments = files.filter(({ buffer }) => buffer == undefined);
    if (new_attachments.length == 0) {
      setFiles([...files, { _id: unique_id() }]);
    }

    const links = files.filter((file) => file.file !== undefined);

    if (links.length !== 0) {
      onFilesChange(links);
    }
  }, [files]);

  return (
    <>
      {files.map((file) => {
          const { _id } = file;
        return ( <FileUpload
              key={_id}
              id={_id}
              onStart={(e) => addFile(e, _id)}
              onFinish={(e) => onFinish(e, _id)}
            />
        );
      })}
    </>
  );
};

export default InlineFileUpload

我認為問題是由於您的此代碼未更新狀態造成的:

  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 不會檢測到更改,也不會更新任何內容。

您可以選擇為您的特定代碼實現深度復制方法或使用 lodash cloneDeep 查看您的代碼,這可能對您const new_files = JSON.parse(JSON.stringify(files))const new_files = JSON.parse(JSON.stringify(files)) 它有點慢,您可能會丟失具有函數或符號等值的屬性。

你得到舊日志的原因是因為閉包

當您在addFiles函數中執行setFiles(new_files) React 異步更新狀態,但新狀態在下一次渲染時可用。

將被調用的onFinish函數仍然來自第一次渲染,引用該渲染的files 新渲染具有對更新文件的引用,因此下次再次登錄時,您將獲得正確的值。

如果只是關於日志記錄,請將其包裝在useEffect鈎子中,

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

如果是在onFinish處理程序中使用它,則有一些答案可以探索這些選項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM