React和多个表单字段

15
我正在阅读关于 "onChange" 的文档,我很好奇如果我的论坛有多个字段,例如选择框、复选框、文本区域和输入框,我该怎么做呢?我只需要像下面这样做吗:

我在阅读"onChange"的文档,我想知道如果我的论坛有多个字段,例如选择框、复选框、文本区域和输入框,我该怎么做?我只需要像下面这样做吗:

 getInitialState: function() {
    return {textArea: 'Hello!', input: 'World', ...};
  },

回到初始状态,然后处理该字段的更改的相同概念是什么?

3个回答

65

@FakeRainBrigand的答案非常棒。

我想分享一个使用 JavaScript 风格(使用高阶函数)的更短的解决方案:

/** @jsx React.DOM */

var App = React.createClass({
  getInitialState: function () {
    return {
      username: '',
      password: ''
    }
  },
  handleChange: function (key) {
    return function (e) {
      var state = {};
      state[key] = e.target.value;
      this.setState(state);
    }.bind(this);
  },
  render: function(){
    console.log(JSON.stringify(this.getFormData(), null, 4));
    return (
      <div>
        <form>
          Username: <input 
                value={this.state.username} 
                onChange={this.handleChange('username')} />
          <br />
          Password: <input type="password"
                value={this.state.password} 
                onChange={this.handleChange('password')} />
        </form>

        <pre>{JSON.stringify(this.getFormData(), null, 4)}</pre>
      </div>
    );
  }
});

React.renderComponent(<App />, document.body);

2
getFormData() 的定义在哪里? - tdc
@Prefix 你可以将 getFormData 视为 this.state - Junle Li

9

编辑:回顾起来,这个答案很糟糕,请使用 Junle Li 的答案。


是的,您可以完全这样做。然而,当您有许多表单组件时,编写所有处理程序和getInitialState调用可能会非常冗长,那么混合使用怎么样呢?

jsbin

还要查找一下react的valueLink mixin

让我们来看一个示例登录表单的视图。您可以调用this.getFormData()来获取仅包含表单状态的对象,从而允许您在状态中存储其他值。

// create a mixin for our form
var formMixin = makeFormMixin([
    "username",
    "password"
]);

var App = React.createClass({
  mixins: [formMixin],
  render: function(){
    return (
      <div>
        <form>
          Username: <input 
                value={this.state.username} 
                onChange={this.handleUsernameChange} />

          Password: <input type="password"
                value={this.state.password} 
                onChange={this.handlePasswordChange} />
        </form>
      </div>
    );
  }
});

这个函数接收一个字段名称的数组,设置初始状态,并为您提供处理程序函数。然后,您可以选择使用这些函数,或者为特殊情况创建自己的处理程序函数。

function makeFormMixin(fields){
  var mixin = {
    getInitialState: function(){
      var state = {};
      fields.forEach(function(field){

        state[field] = this.props[field] || "";
      }, this);
      return state;
    },
    getFormData: function(){
      var data = {};
      fields.forEach(function(field){
        data[field] = this.state[field];
      }, this);
      console.log(data);
      return data;
    }
  };

  fields.forEach(function(field){
    var method = camelJoin(["handle", field, "change"]);
    mixin[method] = function(event){
      var update = {};
      update[field] = event.target.value;
      this.setState(update);
    }
  });

  return mixin;
}

// helper function ["Makes", "things", "camel", "case"] => "makesThingsCamelCase"
function camelJoin(parts){
  return parts.map(function(part, i){
    if (i === 0) {
      return part[0].toLowerCase() + part.slice(1);
    }
    else {
      return part[0].toUpperCase() + part.slice(1);
    }
  }).join("");
}

2
我真的不得不克制自己,不点赞这个回答。你是对的 - 李俊乐的答案更好(因此我最终选择不为你的答案点赞)。但你确实值得赞扬,因为你自己指出了这一点。我希望有一种方法可以给谦卑和诚实加分 - 这两个品质通常不被充分评价。这条评论是我不够充分地表达我的方式:致意。感谢你的贡献! - Johannes Pille
1
@FakeRain mixin 不再受支持。 - angry kiwi
@angrykiwi 看看另一个答案。此外,mixins 仍然在 createClass 中得到支持,并且您可以使用 react-mixin npm 包在 es6 类上使用它们。 - Brigand

0

今天我的一些朋友正在讨论这个问题。@JunleLi提出的解决方案非常好,但它会破坏Purerender,每次在一个字段中输入字符时都会强制重新渲染所有子组件,因为它正在重新生成函数。

以下是我们解决方案的示例。我们仍然不确定是否完全满意,但它最终只创建一次函数并将其缓存。

我很想听听任何反馈意见。

handleChange(key) {
    if(!this.changeHandlers) this.changeHandlers = {};
    return this.changeHandlers[key] || (this.changeHandlers[key] = event => this.setState({[key]: event.target.value}));
},

render() {
    return (
        <div>
          <input type="text" value={this.state.familyName} onChange={this.handleChange("familyName")} />
          <pre>{JSON.stringify(this.state, null, 4)}</pre>
        </div>
    );
}

1
此外,如果有人使用lodash或underscore,可以通过将回调函数创建器包装在_.memoize中轻松实现缓存。 - krzychek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接