反应道具未定义

时间:2018-04-06 21:56:37

标签: javascript reactjs undefined react-props

我正在开发Free Code Camp的React Recipe Box项目。我有一个显示配方名称的父组件,它作为道具接收。可以单击配方名称以显示子组件,然后将子组件传递给子组件以显示有关组件的信息。我的问题是,当我单击配方名称时,父组件中的props将变为未定义。谷歌搜索了一堆,但我无法弄清楚为什么会发生这种情况。有没有人遇到过这个?

import React, { Component } from 'react';
import ShowRecipe from './recipeDetail';


class RecipeDetail extends Component {
  constructor(props){
    super(props)
    this.state = {
      isHidden:true
    }
  }

  render() {
    return (
      <div className="card">
        <div className="card-header">
          <h5>

            <button
              className="btn btn-link"
              onClick={() => {
                this.setState({isHidden: !this.state.isHidden})
              }} 
            >
              {this.props.recipe.recipeName}
            </button>

          </h5>
        </div>

        { !this.state.isHidden &&
          <ShowRecipe
            ingredients={this.props.recipe.ingredientsList}
          />
        }
      </div>
    );
  }
}

export default RecipeDetail;

这是RecipeDetail的道具来自:

import React from 'react';
import RecipeDetail from './recipeDetail';
import { Jumbotron, ListGroup } from 'react-bootstrap';

const RecipeBoxHolder = ({recipes}) =>{

 const recipesItems = recipes.map((recipe) => {
  console.log(recipes);
   return(
     <RecipeDetail
      key={recipe.recipeName}
      recipe={recipe}
     />
  )
 })
 return(
   <div>
    <Jumbotron className="jtron">
     <h5>Recipes</h5>
      <ListGroup>
       {recipesItems}
      </ListGroup>

    </Jumbotron>
   </div>
  )
}

export default RecipeBoxHolder;

TypeError:无法读取undefined的属性'recipeName' RecipeDetail.render SRC /组件/ recipeDetail.js:22

     19 |   <button
     20 |     className="btn btn-link"
     21 |     onClick={() => {this.setState({isHidden: 
                !this.state.isHidden})}}  >
   > 22 |      {this.props.recipe.recipeName}
     23 |  </button>
     24 | 
     25 | </h5>

这来自一个不同的组件,用户输入输入并将其传递给应用程序的主要父组件

    let recipeObject={
       recipeName: this.state.recipe,
       ingredientsList: this.state.ingredients
   };

组件,其中用户输入数据,获取数据并将其传递回主要父组件     从'react'导入React,{Component};     从'react-bootstrap'导入{ListGroupItem};

class AddModal extends Component{
  constructor(props){
    super(props)
    this.state={
      recipe: '',
      ingredients: ''
    }
  } 


  render(){
  let recipeObject={
  recipeName: this.state.recipe,
  ingredientsList: this.state.ingredients
};

  return(
    <ListGroupItem>
      <div className="card">
        <div className="card-header">
         <span>Add Recipe</span> <i className="fas fa-utensils"></i>
       </div>
     <div className="card-body">
        <label>Recipe</label>
       <input value={this.state.recipe} onChange={event => 
           this.setState({recipe: event.target.value})} type="text" 
           className="form-control"/>
       <label className="add-ingredients-label">Add Ingredients</label>
          <textarea value={this.state.ingredients} onChange={event => 
          this.setState({ingredients: event.target.value})} 
          className="form-control"></textarea>
      </div>
         <div className="card-footer">
           <button className="close-button btn btn-outline-danger btn- 
                sm">
           Close
              <i className="fas fa-times"></i>
         </button>
         <button onClick={e =>{this.props.addRecipe(recipeObject)}} 
             className="btn btn-outline-success btn-sm">
            Add Recipe
            <i className="fas fa-plus"></i>
        </button>
         </div>
        </div>
    </ListGroupItem>
    );
  }
 }


 export default AddModal;

这是主要的父组件:

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

import RecipeBoxHolder from './components/recipeContainer';
import AddModal from './components/addRecipeModal';
import './style/index.css';
import {Button, Modal} from 'react-bootstrap';

class App extends Component{
  constructor(props){
    super(props);
    this.state={
      recipes:[],
      showAddModal: false
    }
  }

  render(){
    const addRecipe = (recipeObject) =>{
      this.setState(prevState => ({
        recipes:[...prevState.recipes, recipeObject]}
      ))
    }

    return(
      <div className="container">
        <RecipeBoxHolder recipes={this.state.recipes} />
        <Button
          bsStyle="primary"
          bsSize="large">
        </Button>
        <AddModal addRecipe={addRecipe} />
      </div>
    ) 
   }
 }


   ReactDOM.render(<App />, document.getElementById('root'));

1 个答案:

答案 0 :(得分:1)

@Esteban Trevino我把我的发现归结为答案,因为评论太长了,但我没有解决方案,因为我无法重现你的问题。

我将您的代码复制到create-react-app生成的反应支架中,运行正常。在这个要点中,您可以看到我制作的文件: https://gist.github.com/femans/22324382a8e04390f6a0ece49b867708

我想指出你不应该使用recipeName作为键,因为它们在设计上并不是唯一的。更好地使用以下结构:

const recipesItems = recipes.map((recipe, key) => { return( <RecipeDetail key={key} recipe={recipe} ...

相关问题