簡體   English   中英

React DOM 未在 state 更改時更新

[英]React DOM not updating on state change

我有一個反應組件,它將接受任意數量的文件,每個文件都有自己的語言。 我希望能夠有一個按鈕,讓用戶可以添加任意數量的文件,每個文件都有自己的語言下拉菜單。 我現在已經消除了文件上傳,因為我隔離了我遇到的問題。

我已經毫無問題地創建了很多類似的組件,但由於某種原因,我在這個組件上遇到了很大的麻煩。 當我更改下拉菜單中的語言時,我控制台日志 state 並看到該語言已在 state 中更新,但它不會在我的 map 方法中更新 DOM。

這是我的代碼

function App() {
  const [files, setFiles] = useState([]);

  const languages = ["English", "Spanish", "Arabic", "French"];

  const handleAddFile = e => {
    let newFiles = files;
    newFiles.push({
      content: null,
      preview: null,
      language: ""
    });
    setFiles(newFiles);
  };

  const changeLanguage = (event, index) => {
    let newFiles = files;
    newFiles[index].language = event.target.value;
    setFiles(newFiles);
  };

  console.log(files);

  return (
    <div>
      <p>Files</p>
      <p>Upload a file for as many languages as you have</p>
      {files.map((file, index) => (
        <div key={index}>
          <p>current language: {file.language}</p>
          <select
            value={file.language}
            onChange={event => changeLanguage(event, index)}
          >
            <option value="" disabled>
              Select a language
            </option>
            {languages.map((lang, i) => (
              <option value={lang} key={i}>
                {lang}
              </option>
            ))}
          </select>
        </div>
      ))}
      <button onClick={e => handleAddFile(e)}>+ Add File</button>
    </div>
  );
}

我還制作了一個 codesandbox 來重現這個問題,但它實際上使事情變得更加復雜。 當我在本地運行代碼時,我可以很好地添加文件實例,但是 select 元素上的語言不會在任何實例的 DOM 上更新。 在 codesandbox 中,DOM 上沒有任何更新,除非我在編輯器中進行編輯,然后所有內容都會按照我的預期進行更新,包括語言。 在所有情況下,state 都完全按照我的預期記錄在控制台中。 沙箱中的組件與我在本地擁有的相同,盡管它在本地嵌入到另一個組件中。

https://codesandbox.io/s/ed4fx?file=/src/App.js:0-1248

問題出在handleAddFilechangeLanguage兩種方法中,您直接訪問 state 值文件,因此要進行更新,您需要獲取副本並進行更改並設置新值。

您需要在兩種方法中進行的更新

let newFiles = files;

let newFiles = [...files];

正如@Brian 建議的那樣,當您在changeLanguage方法中更新像語言這樣的深層嵌套值時。 您可以執行如下所示的操作,這樣它就不會改變 state。

const changeLanguage = (event, index) => {
  let newFiles = [...files];
  newFiles[index] = { ...newFiles[index], language: event.target.value };
  setFiles(newFiles);
};

檢查此工作代碼和框

更好的解釋在這里

暫無
暫無

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

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