为什么我的添加功能不起作用?

时间:2016-10-01 22:11:14

标签: javascript reactjs react-jsx jsx

我试图获取用户输入到模态输入框的值,然后将它们添加到我的状态数组中。我试图从输入中获取值,然后将它们推入我的状态数组的克隆中,然后将状态设置为克隆。但是,这种方法似乎不起作用。如果有人可以加入,我将不胜感激。

    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')
  )

2 个答案:

答案 0 :(得分:1)

问题在于,无论何时单击按钮,都会提交表单并重新加载页面。

一种解决方案是从{0}取出按钮,然后在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属性访问输入值并设置状态。

答案 1 :(得分:0)

您的代码中可以改进的一些事项。

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

通过在数组上使用push()方法,您实际上是通过将新项目推入其中来修改组件的state。强烈建议您不要在不使用setState method的情况下直接改变React组件的状态。

解决这个问题的方法是创建一个新数组,在该数组中您将复制所有现有食谱以及您要添加的新食谱。

如果您使用的是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方法“阻止”发生默认操作(即提交表单)。 / p>

以下是jsBin链接,其中包含您可以查看的上述更改。