TypeError:从服务器获取数据时无法读取未定义的属性“ map”

时间:2019-08-04 12:39:44

标签: javascript reactjs firebase firebase-realtime-database

我正在从服务器中获取数据并成功获取数据,如屏幕截图所示,我还检查了我的代码。当我手动获取数据时,我的代码可以正常工作,但是我不知道为什么会收到此错误:

  

TypeError:无法读取未定义的属性“ map”

enter image description here

Orders.js文件:

import React, { Component } from 'react';
import Toolbar from '../../components/Navigation/Toolbar/Toolbar';
import Order from '../../components/Order/Order';
import axios from 'axios';

class Orders extends Component {

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

        this.componentDidMount=(event) =>{

            axios.get('https://reactjs-burger-builder-2607.firebaseio.com/orders.json')
              .then(response =>{
                console.log(response.data)
                let updatedOrders=[];
                for(let key in response.data)
                {
                    updatedOrders.push(response.data[key]);
                }
                this.setState({
                    orders:[].concat(updatedOrders),
                });
            })
        }     
}

  render() { 

      console.log(this.state.orders);

      let allOrders='loading..'; 
      if(this.state.orders){
          allOrders= <Order orders={this.state.orders}/>
      }

    return (
        <div>
        <Toolbar/>
        {allOrders}
        </div>    
    );
  }
}

export default Orders;

Order.js文件

import React from 'react';
import classes from './Order.css';

const Order =(props) =>{

    console.log(props.orders);

    return(  
        <div>
         {props.orders.map(order =>
          <div className={classes.order} key={Math.random()}>
              <span>name: {order.name} </span><br/>
              <span>contact: {order.contact} </span><br/>
              <span>address: {order.address} </span><br/>
              <span>Price: {order.price} Rs </span><br/>
              <p><span>ingredients: </span>
              {order.ingredients.map(ingredient =>
                 <span key={Math.random()} className={classes.ingredients}>{ingredient.name} ({ingredient.qty}) </span>
               )}
              </p>
         </div>
        )}

        </div>
    );
}

export default Order;  

3 个答案:

答案 0 :(得分:4)

并非所有订单都具有成分(订单:-LlR57Tm3bO2xX31ywFq)。这就是为什么某些订单失败的原因。您必须先检查订单中是否有配料。

return(  
    <div>
     {props.orders.map(order =>
      <div className={classes.order} key={Math.random()}>
          <span>name: {order.name} </span><br/>
          <span>contact: {order.contact} </span><br/>
          <span>address: {order.address} </span><br/>
          <span>Price: {order.price} Rs </span><br/>
          <p><span>ingredients: </span>
          {order.ingredients ? order.ingredients.map(ingredient =>
             <span key={Math.random()} className={classes.ingredients}>{ingredient.name} ({ingredient.qty}) </span>
           ) : 'No ingredients'}
          </p>
     </div>
    )}

    </div>
);

答案 1 :(得分:2)

我想有一个没有配料的订单。只需在映射之前检查配料是否存在:

{Array.isArray(order.ingredients) && order.ingredients.map(ingredient =>
  <span key={Math.random()} className={classes.ingredients}>{ingredient.name} ({ingredient.qty}) </span>
)}

顺便说一句,您的代码包含两个问题:

  1. 请勿使用Math.random()作为列表元素键,这是对键元素的最坏输入(最好不要使用键)。请参阅https://reactjs.org/docs/lists-and-keys.html
let updatedOrders=[];
for(let key in response.data)
{
  updatedOrders.push(response.data[key]);
}
this.setState({
  orders:[].concat(updatedOrders),
});
  1. 这部分代码没有意义。尤其是命名updatedOffers[].concat(updatedOrders)
  2. 为什么要在构造函数中为componentDidMount分配一个值,而不是ES6中的默认方法声明?您将ES5和ES6混合使用。

答案 2 :(得分:0)

map是Array方法之一,由于您未定义数组对象(订单),因此发生此类型错误。 你也会犯几个错误。我重构订单组件

import React, { Component } from "react";
import Toolbar from "../../components/Navigation/Toolbar/Toolbar";
import Order from "../../components/Order/Order";
import axios from "axios";

class Orders extends Component {
  constructor() {
    super();
    this.state = {
      orders: []
    };
    this.getData = this.getData.bind(this);
  }

  getData() {
    return axios
      .get("https://reactjs-burger-builder-2607.firebaseio.com/orders.json")
      .then(response => {
        this.setState({
          orders: response.data
        });
      })
      .catch(err => console.error(err));
  }

  //this lifecycle method called when component mount
  componentDidMount() {
    this.getData();
  }

  render() {
    console.log(this.state.orders);

    const RenderOrders = () => {
      if (this.state.orders.length) {
        return <Orders orders={this.state.orders} />;
      } else {
        return <p>...loading</p>;
      }
    };

    return (
      <div>
        <Toolbar />
        <RenderOrders />
      </div>
    );
  }
}

export default Orders;