イベントによるコンポーネント間通信

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 では 必要に応じてこのメソッドをコールバックすることができます。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 React 入門