为什么指定道具的对象的属性不起作用?

时间:2019-12-04 05:00:48

标签: reactjs jsx

我已经找到了一个幸运的解决方案,因此即使尝试在线阅读内容,我也不太了解它的工作原理。

我只是想在selectedDish道具中获取评论数组。 selectedDish的状态填充在Main Component的函数中,我正在尝试访问DishDetail组件中的selectedDish的注释数组。

我能够通过以下方式获得评论

{ this.props.selectedDish && this.renderComments(this.props.selectedDish.comments)}

但是当我只执行以下操作并收到此错误“无法读取未定义的属性'comments'”时,我无法:

{ this.renderComments(this.props.selectedDish.comments)}

为什么这样做? this.props.selectedDish.comments是否足以使我能够成功呈现“ renderDish(dish)”功能?

主要组件

import React, { Component } from 'react';
import { Navbar, NavbarBrand } from 'reactstrap';
import Menu from './MenuComponent';
import Dishdetail from './DishdetailComponent';
import { DISHES } from '../shared/dishes';

class Main extends React.Component {

  constructor() {
    super();
    this.state = {
        dishes: DISHES,
        selectedDish: null
    };
   // this.onDishSelect = this.onDishSelect.bind(this);
  }

  onDishSelect(dishId) {
    this.setState({
       selectedDish: dishId
    });
  }

  render() {
    return (
      <div>
        <Navbar dark color="primary">
          <div className="container">
            <NavbarBrand href="/">Ristorante Con Fusion</NavbarBrand>
          </div>
        </Navbar>

        <Menu dishes={this.state.dishes} onClick={(dishId) => this.onDishSelect(dishId)} />
        <Dishdetail selectedDish={this.state.dishes.filter((dish) => dish.id === this.state.selectedDish)[0]} />
      </div>
    );
  }
}

export default Main;

DishDetail组件

import React, { Component } from 'react';
import { Card, CardImg, CardText, CardBody, CardTitle } from 'reactstrap';

export default class Dishdetail extends React.Component {

    constructor(props) {
        super(props);
    }

    renderDish(dish) {

        if (dish != null)
            return (
                <Card >
                    <CardImg width="100%" src={dish.image} alt={dish.name} />
                    <CardBody>
                        <CardTitle>{dish.name}</CardTitle>
                        <CardText>{dish.description}</CardText>
                    </CardBody>
                </Card>
            );
        else
            return (
                <div></div>
            );
    }

    renderComments(comments) {
        let list = (<div></div>);
        if (comments != null) {
            list = (
                <ul className="list-unstyled">
                    {comments.map(c => {
                        return (
                            <li key={c.id}>
                                <p>{c.comment}</p>
                                <p>-- {c.author}, {new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'short', day: '2-digit' }).format(new Date(Date.parse(c.date)))}</p>
                            </li>
                        );
                    })}
                </ul>
            );
        }
        return (
            <div>
                <h4>Comments</h4>
                {list}
            </div>
        );

    }

    render() {

        return (
            <div className="row">

                <div className="col-12 col-md-5 m-1">
                    {this.renderDish(this.props.selectedDish)}
                </div>

                <div className="col-12 col-md-5 m-1">
                    {/* This works: */}
                    { this.props.selectedDish && this.renderComments(this.props.selectedDish.comments)}

                    {/* This doesn't:  */}
                    {/* { this.renderComments(this.props.selectedDish.comments)} */}
                </div>
            </div>
        );
    }
}

3 个答案:

答案 0 :(得分:1)

当尚未加载DISHES时,主要组件第一次呈现props仍为undefined时,其原因可能是DISHES是由某些外部资源启动的。

因此,当this.props.selectedDishundefined时,您将无法访问它的密钥,因为它们不存在。所以反应会引发此错误。

{ this.props.selectedDish && this.renderComments(this.props.selectedDish.comments)}

因此,这确保this.props.selectedDish存在,然后您可以访问它的comments密钥。

答案 1 :(得分:1)

第一次加载组件时,create or replace procedure MaterialModuleChannelCopy(siteId NUMBER, mcIds VARCHAR2, moduleChannelIdMap out mobicopy_list) IS .... begin.... 状态值为null。它只会在以后设置,因此会出现错误。

更改以下代码

CREATE OR REPLACE TYPE "MOBICOPY_LIST" as table of mobiCopy


CREATE OR REPLACE TYPE "MOBICOPY"                                                                                                                   as object(
channelId number(10),
dyId number(10)
)

收件人

selectedDish

将使其起作用。但是我觉得你现在正在做的事情,即空检查然后渲染是一种更强大的方法。

答案 2 :(得分:1)

仅几个指针,您就不需要基于类的组件,因为您没有使用生命周期方法等。 您可以使用解构来减少打字 let {selectedDish:{comments}} = this.props .

您可以使用注释的默认值

解决问题
`const Dishdetail = ({selectedDishes:{comments}}=[]}) => {}  

和渲染中的条件渲染

<div>
{ comments.length > 0 &&
   //map you comments here if you have some

}
</div>`