我对React还是比较陌生,我正在研究ToDo列表样式Recipe app。我向a previous question here询问了有关重构功能组件的信息,以便使配方成分出现在单独的行中,而不是全部显示为一个单独的行段落。
我实现了建议的更改,并使用了第二个.map函数来遍历成分,并成功地将它们显示在单独的行上。但是,现在实施更改后,当用户单击“编辑”按钮并尝试编辑配方成分时,我会收到错误消息。
用于显示配方名称和成分的功能组件(Item.js
)如下:
import React from 'react';
import Button from 'react-bootstrap/lib/Button';
const Item = (props) => (
<div>
<div className="Recipe-Item-Container" key={props.text}>
{props.items.map((item, index) => {
return (
<div className="Recipe-Item" key={index}>
<h3>{item}</h3>
// This p and the map function within it were the changes I made
<p className="ingredients-list">
{props.ingredients[index].map((ingredient, ingredientIndex) => {
return (
<div className="ingredient" key={ingredient}>
{ingredient}
</div>
)
})}
</p>
<div className="buttons-container">
<Button className="edit-button" onClick={() => props.edit(item, index)}>Edit</Button>
<Button className="delete-button" onClick={() => props.delete(item, index)}>Delete</Button>
</div>
</div>
);
}
)}
</div>
</div>
)
export default Item;
现在,当我单击“编辑”按钮并尝试编辑配料表时,出现此错误:
这是我的App.js组件,用于存储状态并将数据传递给Item.js:
import React, { Component } from 'react';
import Item from './Item';
import './App.css';
import ModalComponent from './Modal.js';
import Button from 'react-bootstrap/lib/Button';
import EditModalComponent from './EditModal.js';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
items: ["Pumpkin Pie", "Spaghetti", "Onion Pie"],
ingredients:[
["Pumpkin Puree ", "Sweetened Condensed Milk ", "Eggs ", "Pumpkin Pie Spice ", "Pie Crust "],
["Noodles ", "Tomato Sauce ", "(Optional) Meatballs "],
["Onion ", "Pie Crust "]
],
// Recipe name and ingredients
inputVal: '',
ingredientVal: '',
// Recipe name and ingredients when user is editing existing recipe
inputValEdit: '',
ingredientValEdit: '',
// Controls whether forms are displayed or hidden
showRecipeForm: false,
showRecipeEditForm: false,
// Index to select which recipe item is being edited
editingIndex: ''
};
}
// Get text user inputs for recipes
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
// When user submits recipe this adds it to the list
onSubmit = (event) => {
event.preventDefault()
this.setState({
items: [...this.state.items, this.state.inputVal],
ingredients: [...this.state.ingredients, this.state.ingredientVal],
showRecipeForm: false
});
}
onEditSubmit = (event) => {
event.preventDefault();
const {items, ingredients, inputValEdit, ingredientValEdit, editingIndex} = this.state;
// Selects proper recipe item to edit
items[editingIndex] = inputValEdit;
ingredients[editingIndex] = ingredientValEdit;
this.setState({
items: items,
ingredients: ingredients,
inputVal: '',
ingredientVal: '',
showRecipeEditForm: false
});
}
closeRecipeForm = () => {
this.setState({
showRecipeForm: false,
showRecipeEditForm: false
});
}
// Shows recipe
AddRecipe = (bool) => {
this.setState({
showRecipeForm: bool
});
}
// Is called when one of the edit recipe buttons is clicked, shows RecipeEditForm
edit = (item, index) => {
this.setState({
showRecipeEditForm: !this.state.showRecipeEditForm,
editingIndex: index
});
}
// Deletes recipe item from the list
delete = (item, index) => {
this.setState({
ingredients : this.state.ingredients.filter((_, i) => i !== index),
items: this.state.items.filter((_, i) => i !== index)
});
}
render() {
return (
<div className="container">
<h1>Recipe List</h1>
<ModalComponent
inputVal={this.state.inputVal}
handleChange={this.handleChange}
ingredientVal={this.state.ingredientVal}
onSubmit={this.onSubmit}
addRecipe={this.addRecipe}
showRecipeForm={this.state.showRecipeForm}
closeRecipeForm={this.closeRecipeForm}
/>
<EditModalComponent
inputValEdit={this.state.inputValEdit}
handleChange={this.handleChange}
ingredientValEdit={this.state.ingredientValEdit}
onEditSubmit={this.onEditSubmit}
closeRecipeForm={this.closeRecipeForm}
addRecipe={this.addRecipe}
showRecipeEditForm={this.state.showRecipeEditForm}
/>
<Item
items={this.state.items}
ingredients={this.state.ingredients}
edit={this.edit}
delete={this.delete}
/>
<Button className="add-recipe-button" onClick={this.AddRecipe}>Add New Recipe</Button>
</div>
);
}
}
当用户尝试编辑配料表时,为什么在Item.js
中出现此错误?我认为它涉及onEditSubmit
函数,但不确定。
答案 0 :(得分:1)
因此,我发现您在onEditSubmit
中正在这样做:
ingredients[editingIndex] = ingredientValEdit; // line 57
您处于状态的成分实际上是一个数组数组(多维)。 就像这样:
ingredients:[
["Pumpkin Puree ", "Sweetened Condensed Milk ", "Eggs ", "Pumpkin Pie Spice ", "Pie Crust "],
["Noodles ", "Tomato Sauce ", "(Optional) Meatballs "],
["Onion ", "Pie Crust "]
],
但是在那行代码之后,您的数组变成了这样的样子: 我已经输入“鸡肉棒棒糖”作为例如的配料。
ingredients:[
"Chicken Lollipop",
["Noodles ", "Tomato Sauce ", "(Optional) Meatballs "],
["Onion ", "Pie Crust "]
],
因此,所选索引处的值将变为字符串而不是数组。 在这种情况下,索引0处的值现在是一个字符串。
因此,Item.js
中的渲染函数会中断,因为它试图映射无法映射的字符串。
要解决此问题,您可以将第57行更改为:
ingredients[editingIndex] = [ingredientValEdit];
现在,每个条目将被正确存储为数组,并且您的代码应该可以正常工作。 更新后的数组如下所示:
ingredients:[
["Chicken Lollipop"],
["Noodles ", "Tomato Sauce ", "(Optional) Meatballs "],
["Onion ", "Pie Crust "]
]
其他内容(此答案不是必需的):
但是,由于您始终需要将成分组成一个数组,因此还可以使用定界符来分割输入值,例如:
用户输入的成分为:“棒棒糖,糖果,某物”
在第57行中,您也可以执行以下操作:
ingredients[editingIndex] = ingredientValEdit.split(',');