2016-10-01 4 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

Проблема заключается в том, что при нажатии кнопки форма передается и перезагрузок страниц.

Одно из решений заключается в том, чтобы снять onClick={this.add} с кнопки и добавить onSubmit={this.add} в тег <form>.

Таким образом, в функции 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, нажав на новый пункт в него. Настоятельно рекомендуется не изменять состояние вашего компонента React напрямую, не используя setState method.

Способ исправить это будет путем создания нового массива, в котором вы скопируете все существующие рецепты и новый рецепт, который вы добавляете.

Если вы используете ES6/2015 это даже easier для достижения этой цели:

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

Таким образом, вы не измените состояние компонента перед вызовом setState() метод, таким образом, сохраняя его нетронутым.

Следующей

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

Постарайтесь как можно использовать Refs (ссылки), чтобы получить доступ к входным узлам, таким образом, вы не должны использовать getElementById, потому что это больше в соответствии с остальной части вашего кода реакции.

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 к button и он должен не более длинную форму. By default Элемент кнопки имеет тип submit.

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

И так, делая это вам не нужно, чтобы «предотвратить» действие по умолчанию возникновения (который должен представить форму), используя метод Event.preventDefault() в обработчике onClick функции.

Вот ссылка jsBin с вышеуказанными изменениями, которые вы можете посмотреть.

+0

Большое вам спасибо, я определенно понимаю, что вы подходите и почему. Не могу поверить, что это было простое решение! – Malekaii

Смежные вопросы