我现在用细齿梳子完成了我的代码,我似乎无法看到"配方"属性未定义。我希望一些更有经验的眼睛可以帮助我,找出我犯错的地方。任何帮助将不胜感激。谢谢。
聚苯乙烯。请在下面找到我的代码......它是来自FreeCodeCamp的Recipe Box项目,我跟随Dylan Israel从CodingTutorials360开始。据我所知,除了文档规定的React-Bootstrap的一些更改之外,我的代码与他的代码相同。
import React, { Component } from 'react';
import './App.css';
import Panel from 'react-bootstrap/lib/Panel'
import Button from 'react-bootstrap/lib/Button'
import ButtonToolbar from 'react-bootstrap/lib/ButtonToolbar'
import Modal from 'react-bootstrap/lib/Modal'
import FormGroup from 'react-bootstrap/lib/FormGroup'
import ControlLabel from 'react-bootstrap/lib/ControlLabel'
import FormControl from 'react-bootstrap/lib/FormControl'
import PanelGroup from 'react-bootstrap/lib/PanelGroup'
class App extends Component {
state = {
showAdd: false,
showEdit: false,
currentIndex: 0,
recipes: [
],
newestRecipe: {recipeName:"", ingredients: []}
}
deleteRecipe(index){
let recipes = this.state.recipes.slice();
recipes.splice(index, 1);
localStorage.setItem('recipes', JSON.stringify(recipes));
this.setState({recipes});
}
updateNewRecipe(value, ingredients){
this.setState({newestRecipe:{recipeName: value, ingredients: ingredients}});
}
close = () => {
if(this.state.showAdd){
this.setState({showAdd: false});
} else if(this.state.showEdit){
this.setState({showEdit: false});
}
}
open = (state, currentIndex) => {
this.setState({[state]: true});
this.setState({currentIndex});
}
saveNewRecipe = () => {
let recipes = this.state.recipes.slice();
recipes.push({recipeName: this.state.newestRecipe.recipeName, ingredients: this.state.newestRecipe.ingredients});
localStorage.setItem('recipes', JSON.stringify(recipes));
this.setState({ recipes });
this.setState({newestRecipe: {recipeName: '', ingredients:[]}});
this.close();
}
updateRecipeName(recipeName, currentIndex){
let recipes = this.state.recipes.slice();
recipes[currentIndex] = {recipeName: recipeName, ingredients: recipes[currentIndex].ingredients};
this.setState({recipes});
localStorage.setItem('recipes', JSON.stringify(recipes));
this.close();
}
updateIngredients(ingredients, currentIndex){
let recipes = this.state.recipes.slice();
recipes[currentIndex] = {recipeName: recipes[currentIndex].recipeName, ingredients: ingredients};
localStorage.setItem('recipes', JSON.stringify(recipes));
this.setState({recipes});
}
componentDidMount(){
let recipes = JSON.parse(localStorage.getItem("recipes")) || [];
this.setState({recipes});
}
render() {
const {recipes, newestRecipe, currentIndex} = this.state;
return (
<div className="App container" id="display-box">
{recipes.length > 0 && (
<div>
<PanelGroup accordion id="recipe-list" defaultActiveKey="2">
{recipes.map((recipe, index)=>(
<Panel eventKey={index} key={index}>
<Panel.Heading>
<Panel.Title toggle>{recipe.recipeName}</Panel.Title>
</Panel.Heading>
<Panel.Body collapsible>
<ol>
{recipe.ingredients.map((item)=>(
<li key={item}>{item}</li>
))}
</ol>
<ButtonToolbar>
<Button bsStyle="danger" onClick={(event)=>this.deleteRecipe(index)}>Delete Recipe</Button>
<Button bsStyle="default" onClick={(event) => this.open("showEdit", index)}>Edit Recipe</Button>
</ButtonToolbar>
</Panel.Body>
</Panel>
))}
</PanelGroup>
</div>
)}
<Modal show={this.state.showEdit} onHide={this.close}>
<Modal.Header closeButton>
<Modal.Title>Edit Recipe</Modal.Title>
</Modal.Header>
<Modal.Body>
<FormGroup controlId="formBasicText">
<ControlLabel>Recipe Name</ControlLabel>
<FormControl
type="text"
value={recipes[currentIndex].recipeName}
placeholder="Enter Text" onChange={(event) => this.updateRecipeName(event.target.value, currentIndex)}
/>
</FormGroup>
<FormGroup controlId="formControlsTextarea">
<ControlLabel>Ingredients</ControlLabel>
<FormControl
componentClass="textarea"
onChange={(event) => this.updateIngredients(event.target.value.split(","), currentIndex)}
placeholder="Enter Ingredients [Seperate by Commas]"
value={recipes[currentIndex].ingredients}>
</FormControl>
</FormGroup>
<Modal.Footer>
<Button bsStyle="primary" onClick={(event) => this.saveNewRecipe()}>Save Changes</Button>
</Modal.Footer>
</Modal.Body>
</Modal>
<Modal show={this.state.showAdd} onHide={this.close}>
<Modal.Header closeButton>
<Modal.Title>Add Recipe</Modal.Title>
</Modal.Header>
<Modal.Body>
<FormGroup controlId="formBasicText">
<ControlLabel>Recipe Name</ControlLabel>
<FormControl
type="text"
value={newestRecipe.recipeName}
placeholder="Enter Recipe Name"
onChange={(event) => this.updateNewRecipe(event.target.value, newestRecipe.ingredients)}
>
</FormControl>
</FormGroup>
<FormGroup controlId="formControlTextarea">
<ControlLabel>Ingredients</ControlLabel>
<FormControl
type="textarea"
placeholder="Enter Ingredients [Seperate by Commas]"
onChange={(event) => this.updateNewRecipe(newestRecipe.recipeName, event.target.value.split(','))}
value={newestRecipe.ingredients}
>
</FormControl>
</FormGroup>
</Modal.Body>
<Modal.Footer>
<Button onClick={(event) => {this.saveNewRecipe()}}>Save</Button>
</Modal.Footer>
</Modal>
<Button bsStyle="primary" onClick={(event)=>this.open("showAdd", currentIndex)}>Add Recipe</Button>
</div>
);
}
}
export default App;
答案 0 :(得分:0)
如果我错了,请纠正我,但看起来你没有正确定义你的初始状态,这可能是你得到一个未定义错误的原因。
通常,state最初是在构造函数中定义的,而不是作为单独的对象定义的。当我尝试像你一样定义状态时,我在codepen上遇到了错误。 看看他们如何在这个备忘单中定义状态(在国家之下):https://devhints.io/react。
我已经完成了相同的FreeCodeCamp反应项目,其中一些可能需要很长时间才能弄清楚,但最终它确实值得。希望这可以帮助您找到错误:)
答案 1 :(得分:0)
问题是当没有当前配方时,您正在访问(两次)当前配方数据。这是因为,虽然你没有显示“模态”,但你正在渲染它。
一种可能的解决方案是仅在编辑某些内容时渲染该模态,您可以使用此替换第110-139行:
{ this.state.showEdit &&
<Modal show={this.state.showEdit} onHide={this.close}>
<Modal.Header closeButton>
<Modal.Title>Edit Recipe</Modal.Title>
</Modal.Header>
<Modal.Body>
<FormGroup controlId="formBasicText">
<ControlLabel>Recipe Name</ControlLabel>
<FormControl
type="text"
value={recipes[currentIndex].recipeName}
placeholder="Enter Text" onChange={(event) => this.updateRecipeName(event.target.value, currentIndex)}
/>
</FormGroup>
<FormGroup controlId="formControlsTextarea">
<ControlLabel>Ingredients</ControlLabel>
<FormControl
componentClass="textarea"
onChange={(event) => this.updateIngredients(event.target.value.split(","), currentIndex)}
placeholder="Enter Ingredients [Seperate by Commas]"
value={recipes[currentIndex].ingredients}>
</FormControl>
</FormGroup>
<Modal.Footer>
<Button bsStyle="primary" onClick={(event) => this.saveNewRecipe()}>Save Changes</Button>
</Modal.Footer>
</Modal.Body>
</Modal>
}
请注意,我唯一要做的就是添加该代码块的第一行和最后一行。
答案 2 :(得分:0)
您应该使用构造函数来定义状态并绑定函数saveNewRecipe
constructor(props) {
super(props);
state = {
showAdd: false,
showEdit: false,
currentIndex: 0,
recipes: [
],
newestRecipe: {recipeName:"", ingredients: []}
};
this.saveNewRecipe = this.saveNewRecipe.bind(this);
}