反应useEffect无法正确更新状态

时间:2020-09-01 14:37:11

标签: reactjs firebase async-await react-hooks firebase-storage

我正在尝试通过在组件安装时执行异步操作来更新反应中的状态。我在images道具中有一个图像ID的列表,从头开始,在安装时,该组件应该遍历每个ID,并在Firebase存储中获取图像的实际URL。但是,包含url的数组一次只能在其中获得一个url,尽管已通过images属性将许多id传递给了它。我在做什么错了?

import React, { useEffect, useState } from 'react';
import { Panel, Carousel, Divider } from 'rsuite';
import { storage } from '../../misc/firebase';

const ListingItem = ({ title, images, owner, props }) => {
  const [imageUrls, setImageUrls] = useState([]);

  useEffect(() => {
    for (const img in images) {
      storage
        .ref(`listings/${owner}/images`)
        .child(images[img])
        .getDownloadURL()
        .then(url => setImageUrls([...imageUrls, url])); // this should append the url to imageUrls
    }
  }, []);

  return (
    <Panel
      {...props}
      shaded
      bordered
      bodyFill
      style={{ display: 'inline-block', height: '100' }}
    >
      <Carousel>
        { /* This only ever outputs a single image */ }
        {imageUrls.length !== 0 &&
          imageUrls.map((img, idx) => <img src={img} key={idx} />)}
      </Carousel>
      <Panel header={title}>
        <small>foo</small>
      </Panel>
    </Panel>
  );
};

export default ListingItem;

1 个答案:

答案 0 :(得分:2)

useEffect回调在装入时仅运行一次。挂载时,imageUrls状态变量被初始化为空数组。结果,在useEffect回调中,这是

.then(url => setImageUrls([...imageUrls, url]));

将始终等同于:

.then(url => setImageUrls([, url]));

因为初始数组为空。

请改用回调形式,以便您根据当前状态设置新的状态 ,而不是根据旧的(现在可能已过时)闭包中的变量进行设置:

.then(url => setImageUrls(currentImageUrls => [...currentImageUrls, url]));