反应道具未定义

React Props Undefined

我正在从事 Free Code Camp 的 React Recipe Box 项目。我有一个显示食谱名称的父组件,它作为道具接收。可以单击食谱名称以显示子组件,然后将相同的道具传递给子组件以显示有关成分的信息。我的问题是,当我单击食谱名称时,父组件中的道具变得未定义。我在谷歌上搜索了很多,但我不明白为什么会这样。有人 运行 以前参与过这个吗?

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: 无法读取未定义的 属性 'recipeName' RecipeDetail.render src/components/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'));

@Esteban Trevino 我将我的发现放入一个答案中,因为评论变得太长了,但是我没有解决方案,因为我无法重现您的问题。

我将您的代码复制到 create-react-app 生成的 React 脚手架中,它运行良好。在这个要点中,您可以看到我制作的文件: https://gist.github.com/femans/22324382a8e04390f6a0ece49b867708

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

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