我正在尝试在ReactJS中创建一个可编辑的配方列表。因此,我为每个key
提供了recipe
,这样我就可以更改与某些家长的recipe
中的key
对应的state
来更新配方零件。
我的应用程序的结构就像这样
App(state) --> RecipeList --> RecipeListItems --> IngredientsList
因此,当我尝试使用editRecipe
组件中定义的以下代码中的App
来更新配方时,它没有被更新,我知道原因,这是因为RecipeList
已经有一个RecipeListItem
已使用给定的key
,因此它不会使用相同的密钥更新这些组件。我通过修改key
来解决此问题:
<RecipeListItem recipe={recipe} key={recipe.key} onDelete={onDelete} />
为:
<RecipeListItem recipe={recipe} key={JSON.stringify(recipe)} onDelete={onDelete} />
是否有更好的方法来更新具有特定键的ListItem(我正在关注向下数据流并将state
保留在顶级App
组件中,以便其他组件自动重新呈现)?
到目前为止,这是我的代码:(Codepen Link to test)
let k = 1;
const localStorageKey = "_developerpruthvi_recipes";
class RecipeList extends React.Component {
constructor(props) {
super(props);
}
render() {
let onDelete = this.props.onDelete;
let RecipeItems = this.props.recipes.map(function(recipe) {
return (
<RecipeListItem recipe={recipe} key={recipe.key} onDelete={onDelete} />
);
});
return (
<div>
{RecipeItems}
</div>
);
}
}
class RecipeListItem extends React.Component {
constructor(props) {
super(props);
this.state = {
title: props.recipe.title,
ingredients: props.recipe.ingredients,
key: props.recipe.key
};
}
deleteRecipe(key) {
this.props.onDelete(key);
}
render() {
return (
<div className="recipe">
<div className="recipe-name" data-toggle="collapse" data-target={'#ingredients-'+this.state.key}>
<p>{this.state.title}</p>
</div>
<div id={"ingredients-" + this.state.key} className="collapse">
<IngredientList ingredientsList={this.state.ingredients} />
<button class="btn btn-primary">Edit</button>
<button class="btn btn-primary" onClick={this.deleteRecipe.bind(this,this.state.key)}>Delete</button>
</div>
</div>
);
}
}
class IngredientList extends React.Component {
constructor(props) {
super(props);
}
render() {
let ing = this.props.ingredientsList.split(",");
return (
React.createElement("ul",{className: "list-group"},ing.map(function(i) {
return React.createElement("li",{className: "list-group-item"},i);
}))
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {recipes: [{
title: "Onion Pie 1",
ingredients: "Onions 1,Water 1,Pie Crust 1",
key: k++
},{
title: "Onion Pie 2",
ingredients: "Onions 2,Water 2,Pie Crust 2",
key: k++
},{
title: "Onion Pie 3",
ingredients: "Onions 3,Water 3,Pie Crust 3",
key: k++
}]};
this.getOrStoreRecipesLocalStorage();
this.deleteRecipe = this.deleteRecipe.bind(this);
}
componentDidMount() {
this.editRecipe(1,"Onion Pie 1","Edited Ing 1 , Edited Ingred 2");
}
deleteRecipe(key) {
let recipes = this.state.recipes;
recipes = recipes.filter(function(r) {
return r.key !== key;
});
this.setState({recipes});
}
editRecipe(key,title,ingredients) {
let recipes = this.state.recipes;
for(let i=0;i<recipes.length;i++) {
if(recipes[i].key === key) {
recipes[i].title = title;
recipes[i].ingredients = ingredients;
}
}
this.setState({recipes});
}
getOrStoreRecipesLocalStorage() {
let localRecipes = JSON.parse(localStorage.getItem(localStorageKey));
if(!localRecipes)
localStorage.setItem(localStorageKey, JSON.stringify(this.state));
else {
this.setState({recipes: localRecipes.recipes})
}
}
render() {
return (
<RecipeList recipes={this.state.recipes} onDelete={this.deleteRecipe} />
);
}
}
ReactDOM.render(<App />,document.querySelector('.container'));