Массив иногда воссоздается, а в другое время изменяется - PullRequest
1 голос
/ 09 января 2020

Я пытаюсь реализовать селектор нескольких файлов изображений в моем приложении React.

Это мой элемент ввода:

<input
type="file"
multiple
onChange={handleImageChange}
/>

{renderPhotos(venueImages)}

Это функции, которые вызываются при выборе файлов. :

  const [venueImages, setVenueImages] = useState([]);`
  const renderPhotos = source => {
    console.log(source); ////////log 1

    return source.map(photo => {
      return <img src={photo} key={photo} />;
    });
  };

  const handleImageChange = e => {
    if (e.target.files) {
      const filesArray = Array.from(e.target.files);
      console.log(filesArray); ///////// log 2
      filesArray.forEach(file => {
        const tempUrl = URL.createObjectURL(file);
        console.log(tempUrl); ////// log 3

        setVenueImages([...venueImages, tempUrl]);
      });
    }
  };

Я звоню renderPhotos, чтобы показать предварительный просмотр всех выбранных фотографий перед загрузкой.

Проблема, с которой я сталкиваюсь, заключается в следующем: если я выберу, например, 5 фотографий, только 1 будет отображаться на экране. Я вставил консольные журналы в handleImageChange, и то, что я получаю, запутывает меня еще больше. Второй журнал (я пронумеровал их в своем коде) печатает массив из 5 файлов. После журнала 3 я получу 5 журналов вновь созданных временных URL-адресов для каждого из файлов.

Но журнал 1 будет напечатан только один раз.

Сейчас - если я ' Я нажму на элемент ввода, чтобы выбрать больше файлов, и я получу еще одно изображение. Так что, в основном, каждый раз, когда я выбираю изображения, независимо от того, сколько я выбрал, я получу только еще одно изображение.

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Проблема в том, что вы ссылаетесь на массив venueImages в вашем вызове setVenueImages. Поскольку обновление состояния, выполняемое setVenueImages, является асинхронным, то вы не можете быть уверены, что venueImages содержит все предыдущие обновления состояния.

Функция установки состояния может быть передана функции, которая принимает старое значение, вместо того, чтобы просто передать ему новое значение. Это обеспечит последовательное обновление вашего состояния. Замените ваш setVenueImages вызов следующим:

setVenueImages(prevImages => [...prevImages, tempUrl]);

Дополнительное изменение, которое я предлагаю, - выполнить объединение всех изображений вместо добавления их одно за другим. Это должно быть быстрее.

const handleImageChange = e => {
  if (e.target.files) {
    const filesArray = Array.from(e.target.files).map(file => URL.createObjectURL(file));
    console.log(filesArray); ///////// log 2
    setVenueImages(prevImages => prevImages.concat(filesArray));
  }
};
1 голос
/ 09 января 2020

Это происходит потому, что при сохранении tempUrl сохраняется только один URL. Также не устанавливайте состояние, добавляя изображения по одному.

Обновленная версия вашей handleImageChange функции может быть

const handleImageChange = e => {
    if (e.target.files) {
      const filesArray = Array.from(e.target.files);
      const tempUrls = filesArray.map(file => URL.createObjectURL(file)))
      setVenueImages([...venueImages, ...tempUrls])
    }
};
...