繁体   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