更新:这个答案已经过时了。如果可以,请远离 mixin。我警告过你!
Mixin 已死。万岁组合
起初,我尝试为此使用子组件并提取FormWidget和InputWidget. 但是,我中途放弃了这种方法,因为我想更好地控制生成的inputs 及其状态。
对我帮助最大的两篇文章:
事实证明,我只需要编写两个(不同的)mixin:ValidationMixin和FormMixin. 
这是我如何将它们分开的。
验证混合
验证 mixin 添加了方便的方法来在您的某些状态属性上运行验证器函数并将“错误”属性存储在state.errors数组中,以便您可以突出显示相应的字段。
define(function () {
  'use strict';
  var _ = require('underscore');
  var ValidationMixin = {
    getInitialState: function () {
      return {
        errors: []
      };
    },
    componentWillMount: function () {
      this.assertValidatorsDefined();
    },
    assertValidatorsDefined: function () {
      if (!this.validators) {
        throw new Error('ValidatorMixin requires this.validators to be defined on the component.');
      }
      _.each(_.keys(this.validators), function (key) {
        var validator = this.validators[key];
        if (!_.has(this.state, key)) {
          throw new Error('Key "' + key + '" is defined in this.validators but not present in initial state.');
        }
        if (!_.isFunction(validator)) {
          throw new Error('Validator for key "' + key + '" is not a function.');
        }
      }, this);
    },
    hasError: function (key) {
      return _.contains(this.state.errors, key);
    },
    resetError: function (key) {
      this.setState({
        'errors': _.without(this.state.errors, key)
      });
    },
    validate: function () {
      var errors = _.filter(_.keys(this.validators), function (key) {
        var validator = this.validators[key],
            value = this.state[key];
        return !validator(value);
      }, this);
      this.setState({
        'errors': errors
      });
      return _.isEmpty(errors);
    }
  };
  return ValidationMixin;
});
用法
ValidationMixin有三种方法:validate,hasError和resetError。
它期望类定义validators对象,类似于propTypes:
var JoinWidget = React.createClass({
  mixins: [React.addons.LinkedStateMixin, ValidationMixin, FormMixin],
  validators: {
    email: Misc.isValidEmail,
    name: function (name) {
      return name.length > 0;
    }
  },
  // ...
});
当用户按下提交按钮时,我调用validate. 调用validate将运行每个验证器并填充this.state.errors一个数组,该数组包含验证失败的属性的键。
在我的render方法中,我使用hasError为字段生成正确的 CSS 类。当用户将焦点放在字段内时,我调用resetError以删除错误突出显示直到下一次validate调用。
renderInput: function (key, options) {
  var classSet = {
    'Form-control': true,
    'Form-control--error': this.hasError(key)
  };
  return (
    <input key={key}
           type={options.type}
           placeholder={options.placeholder}
           className={React.addons.classSet(classSet)}
           valueLink={this.linkState(key)}
           onFocus={_.partial(this.resetError, key)} />
  );
}
表单混合
表单混合处理表单状态(可编辑、提交、提交)。您可以使用它在发送请求时禁用输入和按钮,并在发送请求时相应地更新您的视图。
define(function () {
  'use strict';
  var _ = require('underscore');
  var EDITABLE_STATE = 'editable',
      SUBMITTING_STATE = 'submitting',
      SUBMITTED_STATE = 'submitted';
  var FormMixin = {
    getInitialState: function () {
      return {
        formState: EDITABLE_STATE
      };
    },
    componentDidMount: function () {
      if (!_.isFunction(this.sendRequest)) {
        throw new Error('To use FormMixin, you must implement sendRequest.');
      }
    },
    getFormState: function () {
      return this.state.formState;
    },
    setFormState: function (formState) {
      this.setState({
        formState: formState
      });
    },
    getFormError: function () {
      return this.state.formError;
    },
    setFormError: function (formError) {
      this.setState({
        formError: formError
      });
    },
    isFormEditable: function () {
      return this.getFormState() === EDITABLE_STATE;
    },
    isFormSubmitting: function () {
      return this.getFormState() === SUBMITTING_STATE;
    },
    isFormSubmitted: function () {
      return this.getFormState() === SUBMITTED_STATE;
    },
    submitForm: function () {
      if (!this.isFormEditable()) {
        throw new Error('Form can only be submitted when in editable state.');
      }
      this.setFormState(SUBMITTING_STATE);
      this.setFormError(undefined);
      this.sendRequest()
        .bind(this)
        .then(function () {
          this.setFormState(SUBMITTED_STATE);
        })
        .catch(function (err) {
          this.setFormState(EDITABLE_STATE);
          this.setFormError(err);
        })
        .done();
    }
  };
  return FormMixin;
});
用法
它期望组件提供一个方法:sendRequest,它应该返回一个 Bluebird Promise。(修改它以与 Q 或其他Promise库一起使用是微不足道的。)
它提供了方便的方法,例如isFormEditable、isFormSubmitting和isFormSubmitted。它还提供开球的请求的方法,包括:submitForm。您可以从表单按钮的onClick处理程序中调用它。