React Controlled vs. Uncountrolled

受控组件

受控组件:通过 props 设置表单组件的值。如下通过 this.state.name 设置了 input,同时因为不同于 Vue 中 data 可以直接进行修改,this.state 不可直接修改,故需要提供修改后的响应事件 handleNameChange,将修改的值「推」到表单中。

class Form extends Component {
	constructor() {
		super();
		this.state = {
			 name: '',
		};
	}

	handleNameChange = (event) => {
		this.setState({ name: event.target.value });
	};

	render() {
		return (
			 <div>
				<input
					type="text"
					value={this.state.name}
					onChange={this.handleNameChange}
				/>
			</div>
		);
	}
}

这意味着数据(state)和界面(inputs)总是异步的。state 将值给 input,并且 input 向 Form 请求修改当前值。同时意味着表单组件能够立刻响应 input 的变化。

非控组件

class Form extends Component {
	handleSubmitClick = () => {
		const name = this._name.value;
		// do something with `name`
	}

	render() {
		return (
			<div>
				<input type="text" ref={input => this._name = input} />
				<button onClick={this.handleSubmitClick}>Sign up</button>
			</div>
		);
	}
}

非控组件通过 ref 获得输入的值,即将需要的时候才将 field 中值「提」出来。

总结

根据使用场景选择。如果表单很简单,也没有什么复杂的 UI 反馈,非控组件是完全 ok 的。

feature uncontrolled controlled
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

另外

官方针对表单给出了推荐方案 Formik。

如果你想寻找包含验证、追踪访问字段以及处理表单提交的完整解决方案,使用 Formik 是不错的选择。然而,它也是建立在受控组件和管理 state 的基础之上——所以不要忽视学习它们。

参考