使用Fetch后,React无法在setState之后重新渲染

时间:2017-10-11 05:56:38

标签: json reactjs fetch render setstate

我的智慧结束了。我是一个编码新手,试图使用.map()迭代JSON数据并将其显示在React上的卡片中。

我在componentDidMount()下获取数据并使用setState来分配它。这在另一页上完全正常。

但是,在这个页面上,我试图遍历这个对象上的'projects'数组,但每当我尝试将.map()放到products数组中时,我都会遇到错误。

即使有一个简单的console.log,我也会收到错误。

我认为这与异步提取有关,但我看到的所有问题都用setState()解决了这个问题。我不知道该怎么办。

这是我的JSON对象:

    {
    "_id": "59dac308b9267fbcb5d2de32",
    "name": "The Jewelry Counter",
    "description": "Limited edition fine jewelry, handcrafted in the USA",
    "image": "/public/images/tjclogo.png",
    "__v": 0,
    "products": [
        {
            "_id": "59dada32b9267fbcb5d2de37",
            "name": "Opal and cubic zirconia stacking ring set",
            "price": 80,
            "description": "A three ring stacking set that features an arced ring with an opal and cz, one with just glowing cz's and one with a single solitaire prong set opal.",
            "img": "/shopping-cart-app/public/images/ringset.png",
            "quantity": 2,
            "__v": 0,
            "keywords": [
                "ring",
                "opal",
                "cubic zirconia",
                "cz",
                "jewelry",
                "womens",
                "jewelry counter"
            ]
        },
        {
            "_id": "59dadae1b9267fbcb5d2de38",
            "name": "Moonstone Ear Jackets",
            "price": 140,
            "description": "Four teardrop shaped glowing moonstones are prong set and attach to your ear in a simple three piece process that makes it look as though they are floating on your ears.",
            "img": "/shopping-cart-app/public/images/moonearrings.png",
            "quantity": 4,
            "__v": 0,
            "keywords": [
                "earrings",
                "moonstone",
                "jewelry",
                "womens",
                "jewelry counter"
            ]
        },
        {
            "_id": "59dadb79b9267fbcb5d2de39",
            "name": "Horizontal Pyrite Necklace",
            "price": 52,
            "description": "A horizontal bar of hand crushed pyrite is attached to a brass bar on a 16\" brass chain.",
            "img": "/shopping-cart-app/public/images/pyritenecklace.jpg",
            "quantity": 1,
            "__v": 0,
            "keywords": [
                "necklace",
                "pyrite",
                "jewelry",
                "womens",
                "jewelry counter"
            ]
        },
        {
            "_id": "59dadcfbb9267fbcb5d2de3a",
            "name": "Purple Tourmaline Promise Rings",
            "price": 48,
            "description": "Faceted purple tourmaline prong set on an 18K yellow gold vermeil band. This simple ring is perfect for stacking.",
            "img": "/shopping-cart-app/public/images/ring.jpg",
            "quantity": 1,
            "__v": 0,
            "keywords": [
                "ring",
                "tourmaline",
                "jewelry",
                "womens",
                "jewelry counter"
            ]
        }
    ]
}

我有以下代码:

import React, { Component } from 'react';
import StoreCard from '../../StoreCard';
import ProductCard from '../../ProductCard';
import Wrapper from '../../Wrapper';
import Header from '../../Header';
import StoreLogin from "../../StoreLogin";
import Store from "../../Store";
import './Shop.css';

class Shop extends Component {

  constructor(props) {
        super(props);
        this.state = { storeInfo: []};

    }

    // state = {storeInfo: [], 
        // products: []
    // };

   componentDidMount() {
    fetch('/stores/59dac308b9267fbcb5d2de32')
        .then(res => res.json())
        .then((storeInfo) => {this.setState({ storeInfo: storeInfo })})
   }






  render() {
    console.log(this.state.storeInfo) // works,displays the entire JSON object after beig called twice in the console.
    console.log(this.state.storeInfo.name); // WORKS, same as above
    console.log(this.state.storeInfo['products'][1]['name']); //DOES NOT WORK - ERRORS
    // console.log(this.state.storeInfo.products[1].name); //DOES NOT WORK - ERRORS

    return (
     <div>
        <Header location="Search all stores"/>
        <Wrapper>

          <StoreLogin
            id={this.state.storeInfo._id} // works
            userName={this.state.storeInfo.name} // works
            // productName={this.state.storeInfo.products[1].name} //does not work
          >






            </StoreLogin>

      </Wrapper>
      <h1>Shop</h1>
      </div>
    );
  }
}


export default Shop;

当我一次取消注册storeLogin组件中的'console.logs'和'productName'时,我得到3个错误:

Uncaught TypeError: Cannot read property '1' of undefined

然后

proxyConsole.js:54 The above error occurred in the <Shop> component:
    in Shop (created by Route)
    in Route (at App.js:22)
    in div (at App.js:19)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:17)
    in App (at index.js:6)

Consider adding an error boundary to your tree to customize error handling behavior.
You can learn more about error boundaries at https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html

然后

Uncaught TypeError: Cannot read property '1' of undefined

试。

2 个答案:

答案 0 :(得分:0)

原因是你试图访问的数据storeInfo ['products'] [1] ['name']最初在渲染功能中尚不可用。所以你需要检查数据是否存在。为此你可以做的是

render() {
    console.log(this.state.storeInfo.name); // WORKS

    //Move this console inside if
    if ( this.state.storeInfo.products && this.state.storeInfo.products.length) {
        console.log(this.state.storeInfo['products'][1]['name']);
        console.log(this.state.storeInfo.products[0].name); 
    }

    return (
    <div>
        <Header location="Search all stores"/>
        <Wrapper>

        <StoreLogin
            id={this.state.storeInfo._id} // works
            userName={this.state.storeInfo.name} // works
             productName={this.state.storeInfo.products && this.state.storeInfo.products.length &&
 this.state.storeInfo.products[0].name} //<-- Same here
        >
        </StoreLogin>
    </Wrapper>
    <h1>Shop</h1>
    </div>
    );
}

答案 1 :(得分:0)

问题是,你在componentDidMount函数中有一个fetchRequest,然后设置状态,但是在你之前调用你的渲染,并且因为你试图访问this.state.storeInfo.products[0].namethis.state.storeInfo.products是未定义的,因此,您会收到错误,请在使用前进行检查

return (
 <div>
    <Header location="Search all stores"/>
    <Wrapper>

      <StoreLogin
        id={this.state.storeInfo._id} // works
        userName={this.state.storeInfo.name} // works
        productName={this.state.storeInfo.products && his.state.storeInfo.products[0]?
         this.state.storeInfo.products[0].name: ''} 
      >