2016-10-01 29 views
-1

ユーザーがモーダル入力ボックスに入力した値を取得して、それらを状態配列に追加しようとしています。私は、入力から値を取得し、私の状態配列のクローンにプッシュし、クローンに状態を設定しようとしました。しかし、このアプローチはうまくいかないようです。誰もがチャイムができれば私は幸いです。なぜ私の追加機能は機能しませんか?

var Recipes = React.createClass({ 
    // hook up data model 
    getInitialState: function() { 
     return { 
     recipeList: [ 
      {recipe: 'Cookies', ingredients: ['Flour', 'Chocolate']}, 
      {recipe: 'Pumpkin Pie', ingredients: ['Pumpkin Puree', 'Sweetened Condensed Milk', 'Eggs', 'Pumpkin Pie Spice', 'Pie Crust']}, 
      {recipe: 'Onion Pie', ingredients: ['Onion', 'Pie-Crust']}, 
      {recipe: 'Spaghetti', ingredients: ['Noodles', 'Tomato Sauce', 'Meatballs']} 
      ] 
     } 
    }, 

    ingredientList: function(ingredients) { 
    return ingredients.map((ingredient, index) => { 
     return (<li key={index} className="list-group-item">{ingredient}</li>) 
    }) 
    }, 

    eachRecipe: function(item, i) { 
     return (
      <div className="panel panel-default"> 
      <div className="panel-heading"><h3 key={i} index={i} className="panel-title">{item.recipe}</h3></div> 
      <div className="panel-body"> 
       <ul className="list-group"> 
       {this.ingredientList(item.ingredients)} 
       </ul> 
      </div> 
      </div> 
    ) 
    }, 

    add: function(text) { 
     var name = document.getElementById('name').value; 
     var items = document.getElementById('ingredients').value.split(","); 
     var arr = this.state.recipeList; 
     arr.push({ recipe: name, ingredients: items }); 
     this.setState({recipeList: arr}) 
    }, 

    render: function() { 
     return (
      <div> 
      <div> 
      <button type="button" className="btn btn-success btn-lg" data-toggle="modal" data-target="#myModal">Add Recipe</button> 
      <div id="myModal" className="modal fade" role="dialog"> 
      <div className="modal-dialog"> 

      <div className="modal-content"> 
      <div className="modal-header"> 
      <button type="button" className="close" data-dismiss="modal">&times;</button> 
      <h4 className="modal-title">Add a new recipe</h4> 
      </div> 
      <div className="modal-body"> 
      <form role="form"> 
        <div className="form-group"> 
         <label forName="recipeItems">Recipe</label> 
         <input ref="userVal" type="recipe" className="form-control" 
         id="name" placeholder="Enter Recipe Name"/> 
        </div> 
        <div className="form-group"> 
         <label for="ingredientItems">Ingredients</label> 
         <input ref="newIngredients" type="ingredients" className="form-control" 
          id="ingredients" placeholder="Enter Ingredients separated by commas"/> 
        </div> 
        <button onClick={this.add} type="submit" className="btn btn-default">Submit</button> 
        </form> 
      </div> 
      <div className="modal-footer"> 
      <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> 
      </div> 
     </div> 
     </div> 
     </div> 
      { 
      this.state.recipeList.map(this.eachRecipe) 
      } 
      </div> 
      </div> 
     ); 
     } 
    }); 

    ReactDOM.render(
    <Recipes />, 
    document.getElementById('master') 
) 

答えて

1

問題は、フォームが送信されるボタンやページのリロードをクリックするたびに。

解決策の1つは、onClick={this.add}をボタンから取り出し、<form>タグにonSubmit={this.add}を追加することです。

だから、あなたがadd()機能で:

add: function(e) { 
    e.preventDefault(); 
    var form = e.target; 
    var name = form.name.value; 
    var items = form.ingredients.value.split(","); 
    var arr = this.state.recipeList; 
    arr.push({ recipe: name, ingredients: items }); 
    this.setState({recipeList: arr}); 
}, 

まず、あなたはとてもあなたのフォームはページをリロードしませんe.preventDefault()を呼び出します。次に、targetを使用して、name属性を使用して入力値にアクセスし、状態を設定できます。

0

コードで改善できる点はいくつかあります。

add: function(text) { 
    ... 
    arr.push({ recipe: name, ingredients: items }); 
    this.setState({recipeList: arr}) 
    } 

あなたのアレイ上 push()方法を使用することによって、あなたは、本質的に、コンポーネントの stateそれに新しいアイテムを押してを変更しています。 setState methodを使わずにReactコンポーネントの状態を直接変更しないことを強くお勧めします。

これを修正するには、既存のレシピと追加する新しいレシピをすべてコピーする新しいアレイを作成します。あなたはそのままそれを維持するため、setState()メソッドを呼び出す前に、コンポーネントの状態を変更しない

add: function(text) { 
    ... 
    var newRecipe = { 
    recipe: name, 
    ingredients: items 
    }; 
    this.setState({ recipeList: [...this.state.recipeList, newRecipe] }); 
} 

その方法:あなたがES6/2015を使用している場合

それは、これを達成するためにeasierさえです。

add: function() { 
    var name = document.getElementById('name').value; 
    var items = document.getElementById('ingredients').value.split(","); 
    ... 
} 

それはに沿ったよりあるので、あなたがgetElementByIdを使用する必要はありませんそのように、あなたの入力ノードにアクセスするためにRefs(参照)を使用することは可能な限り試してみてください残りの反応コード。フォームを送信し、ここで起こって何か別のページにあなたを取ってからButton要素を防止するために

add: function(text) { 
    var name = this.refs.userVal.value; 
    var items = this.refs.newIngredients.value.split(","); 
    ... 
}, 
render: function() { 
    return (
    <div> 
     ... 
     <input 
      ref="userVal" 
      placeholder="Enter Recipe Name" 
     /> 
     <input 
      ref="newIngredients" 
      placeholder="Enter Ingredients separated by commas" 
     /> 
     ... 
    </div> 
); 
}); 

そして最後に

、あなたはbuttonにボタンのtype属性を設定することができ、それは無いはずフォームを送信してください。 By defaultボタン要素のタイプはsubmitです。

<button onClick={this.add} type="button" className="btn btn-default">Submit</button> 

だからこれを行うことによって、あなたのonClick関数ハンドラでEvent.preventDefault()方法を使用して、(フォームを送信することである)の発生から、デフォルトのアクションを「防ぐ」する必要はありません。

ここには上記の変更点があるjsBinリンクがあります。

+0

ありがとう、私は間違いなくアプローチと理由を理解しています。そのような単純な解決策だとは信じられない! – Malekaii

関連する問題