イベントによるコンポーネント間通信
React ではコンポジットによって、新しいコンポーネントを作成することが推奨されています。
すなわち、多機能のコンポーネントをひとつドンと作るより、単機能の小さいコンポーネントを作り、それぞれのコンポーネントを組み合わせて機能を増やすという考え方です。
このときに、バラバラのコンポーネントが連携して動作するために、疎結合でカスタムイベント処理ができると便利です。
ちなみに疎結合 (loosely coupled) というのは、「結合してもしなくてもいい」というときに使う言葉です。逆に密結合 (tightly coupled) というと「結合しないと動かない」ということになります。
「React コンポーネントの状態とイベント処理」では、DOM イベントの処理をみました。DOM のイベントは主にブラウザからのコールバックになりますが、 ここでは、コンポジットを構成するコンポーネント間でのカスタムイベントの実装方法を説明します。
前置きは長ったらしくなりましたが、実装は簡単です。
ひとことでいうと、プロパティとして関数オブジェクトを受けとるようにしておき、 必要に応じてそれを呼び出すことでイベントを発行する、ということです。
コンポジットを構成するコンポーネント間でのカスタムイベントの実装方法
まず、テキストボックスをラップする MyTextBox という名前のコンポーネントを作成します。
MyTextBox はプロパティでメソッドを受取ることができ、それを使う側がメソッドを設定した時にそれを呼び出します。
import React from 'react';
export default class MyTextBox extends React.Component {
constructor(props){
super(props);
this.state = { s: "" };
this.onChange = this.onChange.bind(this);
}
onChange(e){
this.setState({s: e.target.value});
if(this.props.onMyTextBoxChanged){
this.props.onMyTextBoxChanged(e.target.value);
}
}
shouldComponentUpdate(nextProps, nextState){
return true;
}
render() {
return (
<div>
<input
type="text"
value={this.state.s}
onChange={this.onChange}/>
</div>
);
}
}
ここでは input 要素をラップしているわけですが、onChange イベントハンドラ内で、 プロパティに設定されたメソッドを呼び出しています。
onChange(e){
this.setState({s: e.target.value});
if(this.props.onMyTextBoxChanged){
this.props.onMyTextBoxChanged(e.target.value);
}
}
このコンポーネントを使う側でプロパティを設定しない時には、呼び出しが失敗するので、if で呼び出しが有効そうか確認してから呼び出しています。
ちなみに、何も設定しない場合は undefined になります。
MyTextBox を持つコンポーネント MyArea は次のようにしました。
import React from 'react';
import MyTextBox from './MyTextBox';
export default class MyArea extends React.Component {
constructor(props){
super(props);
this.state = { s: "" };
this.onMyTextBoxChanged = this.onMyTextBoxChanged.bind(this);
}
onMyTextBoxChanged(v){
console.log(v);
this.setState({s: v});
}
shouldComponentUpdate(nextProps, nextState){
return true;
}
render() {
return (
<div>
<MyTextBox onMyTextBoxChanged={this.onMyTextBoxChanged}/>
<div>{this.state.s}</div>
</div>
);
}
}
ここで MyTextBox のプロパティとして、onMyTextBoxChanged というプロパティにメソッドを渡しています。これによって MyTextBox では 必要に応じてこのメソッドをコールバックすることができます。