Обновление состояния на каждой итерации цикла for - PullRequest
2 голосов
/ 31 октября 2019

ребята! У меня проблема при прохождении каждой итерации переменной for-loop мой массив в состоянии остается с 1 элементом. Вот мой ввод
<input accept="image/*" type="file" onChange={handlePhotoChange} multiple/>, и это handlePhotoChange метод

const [images, setImages] = useState([])
const handlePhotoChange = async (event) => {
    const { files } = event.target;

    for (let i = 0; i < files.length; i += 1) {
      const file = files[i];

      if (!file.type.match('image')) {
        continue;
      }

      setImages([...images, { loading: true, src: null }]);
      await firebase.doUploadImage(file, auth.uid);
      const url = await firebase.getImageUrl(file.name, auth.uid);
      setImages([...images.slice(0, -1), { loading: false, src: url }]);
    }
}

Что я делаю здесь, это задаю для переменной загрузки значение true перед загрузкой изображения в хранилище базы данных и этим loading показываю загрузчик. Затем моя загрузка готова, и я получаю URL-адрес изображения для firebase и перезаписываю последний элемент в массиве images []. Затем мы продолжим со следующим изображением. Таким образом, я собираюсь показать загрузчик на каждом изображении. Но проблема в том, что массив images после цикла содержит только последний добавленный элемент. Я предполагаю, что это что-то с функцией setImages, которая асинхронна, но ждет вашего мнения. Спасибо:)

Ответы [ 2 ]

0 голосов
/ 31 октября 2019

Это асинхронное изменение состояния только один раз. Также, если вы хотите получить доступ к предыдущему состоянию, вы должны использовать версию обратного вызова useState

const [stateObject, setObjectState] = useState({
  firstKey: '',
  secondKey: '',
});

setObjectState((prevState) => ({
  ...prevState,
  secondKey: 'value',
}));

, вы можете разделить состояния загрузки и загруженные состояния, чтобы упростить управление, псевдокод ниже

const handlePhotoChange = (event) => {
  const { files } = event.target;
  const loadingImages = [];
  for (let i = 0; i < files.length; i += 1) {
    const file = files[i];

    if (!file.type.match('image')) {
      continue;
    }
    loadingImages.push({ file });

    firebase.doUploadImage(file, auth.uid)
      .then(// add to uploaded images state)
  }
  // set loading images state after iteration is complete
}
0 голосов
/ 31 октября 2019

Если я правильно понимаю ваш вопрос, может ли решение, подобное этой работе:

const [images, setImages] = useState([]);

const handlePhotoChange = async (event) => {
    const { files } = event.target;

    setImages([...images, { loading: true, src: null }]);

    let newImagesArray = [];

    for (let i = 0; i < files.length; i += 1) {
      const file = files[i];

      if (!file.type.match('image')) {
        continue;
      }

      await firebase.doUploadImage(file, auth.uid);
      const url = await firebase.getImageUrl(file.name, auth.uid);
      let obj = {loading: false, src: url};
      newImagesArray.push(obj);
    }

    //get state
    let newImages = images;
    //add new images
    newImages.push(newImagesArray)
    //update state
    setImages(newImages);
}

То, что мы делаем, - это создание временного массива newImages для хранения всех новых файлов. Затем, как только мы перебираем все загруженные файлы, мы помещаем массив в состояние.

Дайте мне знать, если он работает / если есть проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...