在React.JS中基于键更新组件

时间:2016-06-19 17:42:30

标签: javascript reactjs

我正在尝试在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'));

0 个答案:

没有答案