我正在开发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'));
答案 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}
...