setState не отображает компонент

#javascript #reactjs #render #setstate

#javascript #reactjs #визуализация #setstate

Вопрос:

Итак, я работаю над своим приложением React, и в какой-то момент мне нужно загрузить некоторые файлы. Поэтому я просто использовал input file , чтобы заставить его работать. Я установил его отображение none, так как хотел, чтобы при загрузке файла нажимался значок моего вложения.

Проблема: при использовании метода ref все работает нормально, за исключением одной вещи, которая приведена ниже в моей функции hangleFileChange, когда setFiles() устанавливает переменную file, компонент не отображается, и я не вижу файловый массив. но если я сохраню файл просто, как

 setFile(event.target.files[0])
  

Я вижу рендеринг. Но с приведенным ниже кодом компонент не отображается

 import React, { useRef, useState } from "react";
const App = () => {
  const fileInput = useRef(null);
  const [file, setFile] = useState([]);

  const handleClick = () => {
    fileInput.current.click();
  };

  const handleFileChange = (event) => {
    console.log("Make something");
    let newFiles = file;
    newFiles.push(event.target.files[0]);
    console.log(newFiles);
    setFile(newFiles);
  };

  // This should run on every render
  console.log("the files array is ", file);
  return (
    <div className="patientactions-container">
      <input
        type="file"
        style={{ display: "none" }}
        onChange={(e) => handleFileChange(e)}
        ref={fileInput}
      />
      <div onClick={() => handleClick()}>clck</div>
    </div>
  );
};
export default App;

  

Пожалуйста, помогите.

Песочница: https://codesandbox.io/s/kind-breeze-czc3w?file=/src/App.js:0-692

Комментарии:

1. Если я вас правильно понял, вы хотите перенести файл в переменную, не так ли?

2. переменная — это просто временная переменная. Я хочу добавить новый файл, загруженный пользователем, в мой файловый массив. Поэтому я взял временную переменную ‘ne’ и скопировал значения file. Затем я нажал новый файл, а затем SetFile(ne). вы поняли?

3. Позвольте мне опубликовать это в ответе

4. Я изменил код и использовал SetFile ( [ …file, event.target . files[0] ] ); И теперь это рендеринг. Но я все еще не понимаю, почему приведенный выше код не работает.

Ответ №1:

Попробуйте эту версию

 const handleFileChange = (event) => {
    console.log("Make something");
    // Set the ne variable to an array, not file
    let ne = [];
    ne.push(event.target.files[0]);
    // then set it equals file.
    ne = file;
    console.log(ne);
    console.log(file);
    setFile(file);
  };
  

Ответ №2:

Вы можете исправить код, подобный приведенному ниже.

 import React, { useRef, useState } from "react";
const App = () => {
  const fileInput = useRef(null);
  const [file, setFile] = useState(null);

  const handleClick = () => {
    fileInput.current.click();
  };

  const handleFileChange = (nfile) => {
    console.log("Make something");
    if (file == null) setFile([nfile]);
    else setFile([...file, nfile]);
  };
  console.log("the files array", file);
  return (
    <div className="patientactions-container">
      <input
        type="file"
        style={{ display: "none" }}
        onChange={(e) => handleFileChange(e.target.files[0])}
        ref={fileInput}
      />
      <div onClick={() => handleClick()}>clck</div>
    </div>
  );
};
export default App;
  

Комментарии:

1. Да, я сделал то же самое, что и выше, и повторный рендеринг выполняется нормально. Но я хочу знать, что не так в моей функции handleFileChange, поскольку она также делает то же самое.

2. это потому, что с самого начала файл пуст, и вы устанавливаете новый файл в пустой массив … помните, что код читается сверху вниз

Ответ №3:

Я бы написал это в комментариях, но моя репутация недостаточно высока.

У меня была проблема с отображением изменений в массиве, поскольку массивы используют указатели, которые не «регистрировали» изменение состояния, которого было достаточно, чтобы вызвать рендеринг. Использование оператора распространения в вашем решении повлияло на указатель, и, таким образом, произошел рендеринг.

В моем собственном решении я установил для своего массива значение null перед добавлением содержимого, и это отлично сработало для моей проблемы.