React - 表单组件中状态的最佳实践?

时间:2016-02-23 10:46:37

标签: javascript forms reactjs

我正试图了解有关反应成分状态的最佳实践。我开始通过编写TextField组件来创建表单,如下所示

var TextField = React.createClass({
    render: function() {
        const {value, title, placeholder} = this.props;
        return (<div>
            {title}
            <input type="text"
                value={value}
                placeholder={placeholder}
                onChange={this.handleChange} />
        </div>);
    },

    handleChange (evt){
        this.props.onChange(evt.target.value);
    }
});

这是一个受控制的组件。因此父容器必须为via输入中的输入传递值,并在发生更改时更改该值。这似乎是通常的做法。

当我想创建一个数字字段时,我的问题出现了。对于此示例,假设我的数字字段将允许输入非数字字符(该字段不会验证)。我不喜欢在父母中验证该字段的想法,所以这就是我写的

var NumericField = React.createClass({

    getInitialState: function(){
        return{
            value : ""
        }
    },

    componentWillReceiveProps: function(nextProps) {
        if(this.validate(nextProps.value)){
            this.setState({value:nextProps.value});
        }
    },

    validate : function(input) {
        return !isNaN(input);
    },

    render: function() {
        const {value} = this.state;
        const {title} = this.props;
        return (<div>
            {title}
            <input type="text"
                value={value}
                onChange={this.handleChange} />
        </div>);
    },

    handleChange (evt){
        this.setState({value:evt.target.value});
        if(this.validate(evt.target.value)){
            this.props.onChange(evt.target.value);
        }
    }
});

这允许父级设置值并通过“value”prop更新它,但“onChange”prop只会在内容有效时触发。我觉得我每次都使用不同的模式,这并不好。不确定这是否是一种有效的感觉?

我想我只是想问一下我对数字字段的处理方式是否合理,或者是否有更好的模式可供使用?

万一有人想知道为什么我希望数字字段以这种方式工作,我不这样做,这只是一个简化的例子。一个更有效的例子是json的文本区域,当内容是有效的json时,它只调用onChange。

感谢任何反馈

1 个答案:

答案 0 :(得分:2)

通过传递道具来设置状态通常是不受欢迎的。 道具应该是不可变的(就像你的NumericField组件的标题) 如果你想设置一个初始值,它应该来自控制器或父组件从中获取的存储,例如。

&#13;
&#13;
getInitialState() {
  return({
    value: FormDataStore.getInitialNumericFieldValue()
  });
}
&#13;
&#13;
&#13;

之后,对值的任何更改都应由NumericField组件处理。如果您需要在设置新状态之前进行验证,例如

&#13;
&#13;
handleChange(evt) {
  if (this.validate(evt.target.value)){
    this.setState({
      value: evt.target.value
    });
    /* You can also pass the new validated value
       up to the parent component to hold on to
       till you're ready to process the form*/
    this.props.onChange(evt.target.value);
  }
}
&#13;
&#13;
&#13;

您的状态现在只能保留(并且随后父组件将只接收)最后一个经过验证的值,因此如果this.state.value ===输入,您甚至可以显示有效/无效消息,但是该状态为&#39;额外的

顺便说一下,TextField组件也应该遵循这种模式。将更改后的值传递给父级只是为了让它作为一个道具再次传递,这会破坏拥有子组件的目的。在这种情况下,我将在父组件中使用JSX(和任何验证过程),而不是抽象子项。除非儿童组件可以重复使用。但是,我仍然让孩子处理自己的状态。