React受控组件与不受控组件

受控组件与不受控组件

Follow me on GitHub

1. 受控组件(Controlled Components)

在HTML中,表单组件<input>,<textarea>,<select>拥有自身的状态(值),并根据用户的输入进行更新。而在React中,可变状态保存在state中,并只能使用setState()来更新。

我们可以将这两种状态合一,使React的state成为单一数据源(single source of truth),这时渲染form的React组件就可以对表单中的输入进行控制。因此,受控组件就是值受React控制的表单输入元素。

受控组件通过change事件(在用户输入每个字符时触发)和value属性实现。

class NameForm extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            name:'',
            sex:'male',
            profile:''
        };
        this.handleNameChange = this.handleNameChange.bind(this);
        this.handleSexChange = this.handleSexChange.bind(this);
        this.handleProfileChange = this.handleProfileChange.bind(this);
    },
    handleNameChange(e){
        this.setState({name:e.target.value});
    },
    handleSexChange(e){
        this.setState({sex:e.target.value});
    },
    handleProfileChange(e){
        this.setState({profile:e.target.value});
    },
    render(){
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    Name:
                    <input type="text"
                        value={this.state.name}
                        onChange={this.handleNameChange}
                    />
                </label>
                <label>
                    Sex:
                    <select value={this.state.sex} onChange={this.handleSexChange}>
                        <option value="male">male</option>
                        <option value="female">female</option>
                    </select>
                </label>
                <label>
                    Profile:
                    <textarea value={this.state.profile}
                        onChange={this.handleProfileChange}
                    />
                </label>
                <input type="submit" value="Submit" />
            </form>
        )
    }
}

受控组件通过value属性控制输入元素的值,通过change事件处理函数处理所有的用户输入。
如果value设置为一个固定的值,而未设置其change事件处理函数来设置state,输入元素是不可编辑的。
value属性在设置为null或者undefined时,输入元素仍旧是可编辑的。

受控组件需要编写每个输入元素的处理函数,比较繁琐,对于某些输入处理逻辑相同的元素,可通过name属性统一处理。

class MultipleInput extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            address:'',
            alternateAddress:''
        }
        this.handleChange = this.handleChange.bind(this);
    },
    handleChange(e){
        this.setState({
            [e.target.name]:e.target.value
        });
    }
    render(){
        return (
            <form>
                <label>
                    address:
                    <input type="text"
                        name="address"
                        value={this.state.address}
                        onChange={this.handleChange}
                    />
                </label>
                <label>
                    alternate address:
                    <input type="text"
                        name="alternateAddress"
                        value={this.state.alternateAddress}
                        onChange={this.handleChange}
                    />
                </label>
            </form>
        );
    }
}

2. 不受控组件(Uncontrolled Components)

受控组件表单的值由React控制,不受控组件表单的值由DOM控制,其单一数据源保存在DOM中。
不受控组件不需要对每个输入元素编写change事件处理函数来更新状态。在需要获取输入元素的值时可使用ref

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={(input) => this.input = input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

React的value属性会覆盖DOM中表单输入元素的value值。使用不受控组件时,可使用defaultValue属性来指定初始值。

3. 使用场景

场景 受控组件 不受控组件
one-time value retrieval (e.g. on submit)
validating on submit
instant field validation
conditionally disabling submit button
enforcing input format
several inputs for one piece of data
dynamic inputs

可参考controlled versus uncontrolled inputs

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容