Controlled vs Uncontrolled componentsとrefの使い方
Reactでは、状態管理がDOMではなくReact componentで行われる。 Reactなしである場合、例えばformのinput要素の状態を取ってくる場合は従来はDOM操作によって取ってくるという手法だった。
ではどちらの方法がベターであるのか? この質問に付随して出てくるのがControlled componentsとUncontrolled componentsである。
Controlled components
Controlled componentsでは、状態管理をReactのスタイルに沿って行う。 formやinputの状態は全て属するコンポーネントのstateで管理されるので、各値を更新する場合はstateを更新することになる。
Uncontrolled components
Uncontrolled componentsでは、コンポーネントによる状態管理はなく、コンポーネントの状態は各inputで各々持つ。 つまりDOM内に状態が存在するので、更新するにはDOM操作を行う必要がある。
refを使用したinputのDOMでの状態管理
Controlled
Form.js
class Form extends React.Component { constructor(props) { super(props) this.state = { email: '' } this.handleChange = this.handleChange.bind(this) this.handleSubmit = this.handleSubmit.bind(this) } handleChange(e) { this.setState({ email: e.target.value }) } handleSubmit() { alert('The email is ' + this.state.email) } render() { return ( <div> <pre>The email is {this.state.email}</pre> <br /> <input type='text' placeholder='Email' value={this.state.email} onChange={this.handleChange} /> <button onClick={this.handleSubmit}>Submit</button> </div> ) } }
こちらの例の場合は、状態はコンポーネントのstateが持っていることになる。 このコードを、Uncontrolled componentsにしてDOMでの状態管理ができるようにしてみる。
Uncontrolled
Form.js
class Form extends React.Component { constructor(props) { super(props) this.input = React.createRef('') this.handleSubmit = this.handleSubmit.bind(this) } handleSubmit() { alert('The email is ' + this.input.current.value) } render() { return ( <div> <input type='text' placeholder='Email' ref={this.input} /> <button onClick={this.handleSubmit}>Submit</button> </div> ) } }
refのpropをinputフィールドに持たせ、値を取得する際にはthis.input.current.value
で持ってくることができる。
どちらを使用すべきか?
結論からいうとControlled componentsで書いた方がよい。 Reactに状態管理を委ねる方が、変更にたいしてリアクティブなUIを作ることができるから。