2016-08-16 18 views
0

私は非常に奇妙なケースを見つけました。私はReactJSのレシピを含むことができるレシピボックスを作っています。これは、これらの初期のレシピで始まる:Reactjsは、以前に挿入されたオブジェクトに挿入されたオブジェクトを複製します。

var App = React.createClass({ 
    getInitialState: function() { 
    return { 
     recipes: [{ 
     id: 0, 
     name: "Carbonana", 
     ingredients: ["Spaghetti", "Banana-sauce", "Bacon", "Cream", "Oregano"] 
     }, { 
     id: 1, 
     name: "Roasted duck with sweet potatoes", 
     ingredients: ["Duck", "Sweet chili sauce", "Small potatoes", "Sugar", "Butter"] 
     }, { 
     id: 2, 
     name: "Baked potatoes", 
     ingredients: ["Baking potatoes", "Bacon", "Creme Fraiche", "Garlic", "Onions"] 
     }] 
    } 
    } 

次にあなたが経由名や食材を使用して独自のレシピを追加することができます。フォーム。 AddRecipeコンポーネントで:

<Form > 
    <ControlLabel>Recipe Name</ControlLabel> 
      <FormControl 
     type="text" 
     value={this.state.value} 
     placeholder="Beef Cheese" 
     onChange={this.handleRecipeNameChange} 
     /> 
    <hr/> 
    <FormGroup controlId="formControlsTextarea"> 
    <ControlLabel>Ingredients</ControlLabel> 
    <FormControl onChange={this.handleIngredientsChange} 
componentClass="textarea" placeholder="salt,pepper,cheese,beef" /> 
</FormGroup> 
    <ButtonToolbar> 
<Button onClick={this.handleAddRecipe} bsStyle="primary">Add Recipe</Button> 
    <Button onClick={this.closeModal}>Cancel</Button> 

成分は、カンマので区切られた形式で入力することができます。ここで、フォームのハンドル方法がある:AddRecipe成分で

handleAddRecipe: function() { 
    this.closeModal(); 
    this.props.addRecipe(this.state.recipe); 
    }, 

    handleRecipeNameChange: function(e) { 
    var recipe = this.state.recipe; 
    recipe.name = e.target.value; 
    this.setState({recipe: recipe}); 
    }, 

    handleIngredientsChange: function(e) { 
    var recipe = this.state.recipe; 
    recipe.ingredients = e.target.value.split(","); 
    this.setState({recipe: recipe}); 
    } 

最後AddRecipeコンポーネントからレシピを受信し、レシピオブジェクトのレシピアレイに追加addRecipe(レシピ)があります。レシピのそれぞれは、一意のIDが必要です:私は1つのレシピを追加した場合、それは3の一意のIDを取得します

addRecipe: function(recipe) { 
    var currentRecipes = this.state.recipes; 
    console.log("currentRecipes "); 
    console.log(currentRecipes); 
    recipe.id = currentRecipes.length; 
    currentRecipes.push(recipe); 
    console.log("recipe added: "); 
    console.log(recipe); 
    console.log(recipe.id + " last id!"); 
    this.setState({recipes: currentRecipes}); 
    } 

を、これが出力され、これは素晴らしいですし、私が期待どおり:

recipes: [{ 
     id: 0, 
     name: "Carbonana", 
     ingredients: ["Spaghetti", "Banana-sauce", "Bacon", "Cream", "Oregano"] 
     }, { 
     id: 1, 
     name: "Roasted duck with sweet potatoes", 
     ingredients: ["Duck", "Sweet chili sauce", "Small potatoes", "Sugar", "Butter"] 
     }, { 
     id: 2, 
     name: "Baked potatoes", 
     ingredients: ["Baking potatoes", "Bacon", "Creme Fraiche", "Garlic", "Onions"] 
     }, { 
     id: 3, 
     name: "Something new and exciting!", 
     ingredients: ["More beef", "Onions"] 
     }] 

AddRecipeコンポーネントからフォームを再度開いて、新しいレシピを入力します。しかし、それは単に再び同じオブジェクトを挿入します。この時間:

recipes: [{ 
      id: 0, 
      name: "Carbonana", 
      ingredients: ["Spaghetti", "Banana-sauce", "Bacon", "Cream", "Oregano"] 
      }, { 
      id: 1, 
      name: "Roasted duck with sweet potatoes", 
      ingredients: ["Duck", "Sweet chili sauce", "Small potatoes", "Sugar", "Butter"] 
      }, { 
      id: 2, 
      name: "Baked potatoes", 
      ingredients: ["Baking potatoes", "Bacon", "Creme Fraiche", "Garlic", "Onions"] 
      }, { 
      id: 4, 
      name: "Something even more new and improved!!", 
      ingredients: ["Day old potatoes", "salt"] 
      }, { 
      id: 4, 
      name: "Something even more new and improved!!", 
      ingredients: ["Day old potatoes", "salt"] 
      }] 

私が気づく何が、それは以前のすべての入力されたオブジェクト間で、最新の入力されたオブジェクトを複製していることです。どうしてこれなの?あなたは、新しいレシピを追加してからあなたを防ぐことだ問題は、あなたのAddRecipeコンポーネントがthis.props.addRecipeを使用して、その状態に参照を渡しているという事実であるhttp://codepen.io/Hylleh/pen/pbqNbO?editors=1010

+0

;'してから 'currentRecipes'を修正する:私はそうのようなApp.addRecipe機能を変更します。そのようなステートメントを 'var currentRecipes = Object.assign([]、this.state.recipes);'で変更して、もう一度やり直してください。 –

答えて

0

上のアクションでページを見ることができます。

あなたのAppコンポーネントはこの参照を受け取り、それを何度も繰り返して配列に追加します。したがって、この配列のインデックス2を超えるすべてのアイテムは、同じid,name、およびingredientsというプロパティを共有することを意味し、常に同じAddRecipe状態とまったく同じ参照になります。これらのレシピのそれぞれのキーとしてidを使用しているので、追加のレシピがすべて最後のレシピと同じキーを共有するため、Reactは最初に追加したレシピをレンダリングしません。

あなたがそのページでコンソールを開く場合は、次の2つのレシピを追加しようとした後にこのエラーが表示されます:

警告:flattenChildren(...):同じキーを持つが発生しました2人の子供、4 。子キーは一意でなければなりません。 2人の子供がキーを共有する場合、最初の子供だけが使用されます。

この問題の解決策は、Appコンポーネントの状態に、AddRecipeコンポーネントの状態の参照を保存しないようにすることです。あなたは `VAR currentRecipes = this.state.recipesような何かを行うことによって状態オブジェクト自体を変異させ、あなたのコード内のいくつかのポイントがあります

addRecipe(recipe) { 
    // Clone passed state reference and set id to the correct value 
    const newRecipe = Object.assign({}, recipe, { 
     id: this.state.recipes.length 
    }); 

    // Replace recipes with a new array that has newRecipe appended at the end 
    this.setState({ 
     recipes: [...this.state.recipes, newRecipe] 
    }); 
} 
+0

ありがとう、それは今動作します。私は参照を渡っていたことを知らなかった。 – Hylle

+0

お手伝いします:)あなたの問題を解決した場合は、回答を受け入れるようにしてください! –

関連する問題