【问题标题】:React: array value are undefined in map()反应:数组值在 map() 中未定义
【发布时间】:2020-04-15 18:11:41
【问题描述】:

我正在制作渲染来自 firebase 的所有产品的 React 应用程序。我正在获取对象数据并用具有正确 url 链接的新数组替换图像数组。之后,我用对象数组设置状态。一切都很顺利,直到我需要映射该对象数组并从对象的图像数组中获取第一张图像。我可以从对象访问所有数据,也可以获得 images 数组,但是当我指向确切值时 (images[0]) 我得到 undefined em>

我的代码

export default class List extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loaded: false,
            productsArr: []
        }
    }

    componentDidMount() {
        this.setState({
            loaded: true
        })
        db.collection('products').get().then((list) => {
            let productsArr = []
            list.forEach((doc) => {
                let obj = doc.data();
                let imgArr =[];
                obj.images.forEach((img) => {
                    storageRef.child(`images/${img}`)
                    .getDownloadURL()
                    .then(url =>{
                        imgArr.push(url)
                    })
                    .catch(err => {
                        console.log('Getting image url ERROR', err)
                    })
                })
                const newObj = Object.assign(obj, {images: imgArr})
                productsArr.push(newObj)
            })
            this.setState({
                productsArr,
            })
        })
    }


    render() {
        return(
            <div>
                <Header />
                {this.state.loaded ? <Loading /> : null}
                <div>
                    {this.state.productsArr.map((product, i) => {
                        let arr = product.images
                        console.log(arr)
                        return (
                            <div key={i}>
                                <div>
                                    <div>
                                        <img src={product.images[0]}
                                            alt={product.category} 
                                        />
                                    </div>
                                </div>
                            </div>
                        )
                    })}
                </div>
                <Footer />
            </div>
        )
    }
}

对象的外观:

{
   category: "wooden",
   color: "black",
   height: "13",
   id: "103A220",
   images: ["https://firebasestorage.googleapis.com/v0/b/remini…=media&token=8668-deeac8dd21e0"],
   price: "4",
   productName: "Wood",
   warehouse: true,
   width: "14"
}

【问题讨论】:

  • 您能从那个console.log 中看到产品对象吗? console.log(arr)
  • 该日志仅用于测试目的,但使用 arr 变量我可以看到带有值的图像数组。如果我记录 product 那么我可以看到产品对象
  • 试试这个。 this.state &amp;&amp; this.state.productsArr &amp;&amp; this.state.productsArr.map( 因为我尝试了与您实施的相同的事情。渲染部分完全没问题。唯一可能发生的问题是 productArr 没有完全加载到 reder 部分。
  • 我试过了,结果一样undefined
  • 检查 this.state.productsArr 后必须使用渲染。只需添加一个 if 语句 if(this.state.productsArr){render(){your mapping code}} else {render(){return(&lt;div&gt;&lt;/div&gt;)}}

标签: javascript arrays reactjs firebase object


【解决方案1】:

我的猜测:在所有 foreachs 完成之前,对 getDownloadURL() 的调用无法解决。这会导致使用大部分包含空 images 数组的对象来更新状态。

为确保在setState 之前执行所有异步流程,您必须等待承诺解决。

尝试将您的componentDidUpdate() 替换为以下内容:

componentDidMount() {
  db.collection("products")
    .get()
    .then((list) =>
      list.map((doc) => {
        // Get object
        const obj = doc.data();

        // Get all the images urls
        // This returns an array of promises
        const urlsPromises = obj.images.map((img) => {
          return storageRef.child(`images/${img}`).getDownloadURL();
        });

        // Pass the array of promises to Promise.all
        // and receive an array of urls that you assign to the obj.images key
        return Promise.all(urlsPromises)
          .then((urls) => Object.assign(obj, { images: urls }))
          .catch((err) => {
            console.log("Getting image url ERROR", err);
            // In case of error, keep the obj object as it is
            // Handle this as you which, this is an exemple
            return obj;
          });
      })
    )
    // Wait for the array of promises generated in the previous then
    .then(Promise.all)
    // Handle the array of altered obj
    .then((productArr) => this.setState({ loaded: true, productArr }))
    // Handle error as you like
    .catch(console.error);
}

并在您的 render() 方法中更新此条件:

{this.state.loaded ? null : <Loading />}

【讨论】:

  • 您能详细说明一下吗?喜欢提供有关错误的一些详细信息吗?
  • 它只是输入错误:TypeError: list.map is not a function at list.js:23
  • list 不是数组?
  • 您的实体可能是Map,然后只需执行Array.from(list.entries()).map(.... ) 将其转换为数组并链接地图。
  • 现在出现错误:TypeError: list.entries is not a function
猜你喜欢
  • 2019-08-25
  • 2020-05-17
  • 2018-05-09
  • 2022-12-20
  • 2021-08-18
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 2018-10-06
相关资源
最近更新 更多