【问题标题】:Why does my add function not work?为什么我的添加功能不起作用?
【发布时间】:2016-10-01 22:11:13
【问题描述】:

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

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

【问题讨论】:

    标签: javascript reactjs react-jsx jsx


    【解决方案1】:

    问题在于,每当您单击按钮时,表单都会提交并且页面会重新加载。

    一种解决方案是将onClick={this.add} 从按钮中取出并在&lt;form&gt; 标记处添加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 通过他们的names 属性访问输入值并设置状态。

    【讨论】:

      【解决方案2】:

      您的代码中有一些可以改进的地方。

        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>
      

      因此,通过这样做,您无需使用onClick 函数处理程序中的Event.preventDefault() 方法“阻止”发生默认操作(即提交表单)。

      这是一个jsBin 链接,上面有您可以查看的更改。

      【讨论】:

      • 非常感谢,我绝对理解您的做法以及原因。我不敢相信这是一个如此简单的解决方案!
      猜你喜欢
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      • 1970-01-01
      相关资源
      最近更新 更多