原文: How to Pass Data and Events Between Components in React

API エンドポイントを利用する CRUD 操作を実装しようとすると、複数のコンポーネントにまたがるデータ管理の難しさに気付くでしょう。

あるいはモーダルを異なるコンポーネントからトリガーしたいこともあるでしょう。

そのような場合の対応方法は、なかなか理解が難しいかもしれません。

このチュートリアルでその方法を解説します。

親コンポーネントから子コンポーネントにデータを受け渡す方法

はじめに、親コンポーネントと子コンポーネントの間でデータを受け渡す場合を考えます。

まず、親と子にあたる 2 つのコンポーネントを作成します。

import React from 'react'

export default function Parent() {
  return (
    <div>
      
    </div>
  )
}
Parent.js
import React from 'react'

export default function Child() {
    return (
        <div>
            
        </div>
    )
}
Child.js

次に、Parent コンポーネントで Child コンポーネントをインポートして返します。

import React from 'react'
import Child from './Child';

export default function Parent() {
  return (
    <div>
      <Child/>
    </div>
  )
}
Parent コンポーネント内で Child コンポーネントを呼び出す

そして関数と、その関数をトリガーするボタンを作成します。さらに useState フックを使用して、データを管理する state を作成します。

import React from 'react'
import Child from './Child';
import { Button } from 'semantic-ui-react';
import { useState } from 'react';
import './App.css';

export default function Parent() {
  const [data, setData] = useState('');
  
  const parentToChild = () => {
    setData("This is data from Parent Component to the Child Component.");
  }
  return (
    <div className="App">
      <Child/>
      
      <div>
        <Button primary onClick={() => parentToChild()}>Click Parent</Button>
      </div>
    </div>
  )
}

上記のコードでは、Click Parent ボタンがクリックされた時に parentToChild 関数を呼び出します。Click Parent ボタンがクリックされると、data 変数に "This is data from Parent Component to the Child Component" が格納されます。

では次に、その data という state を Child コンポーネントに受け渡します。これは props を用いて実現できます。

下記のように、Child コンポーネントを呼び出す際に data を props として受け渡します。

<Child parentToChild={data}/>
Parent.js

ここでは data というデータを Child コンポーネントに受け渡しています。

data が受け渡したいデータで、parentToChild が props の名前です。

次は、そのデータを Child コンポーネント側で受け取ります。これはとてもシンプルです。

これには 2 通りのケースがあります。

ケース 1: 関数コンポーネントを使用している場合は、引数で parentToChild を受け取ります。

import React from 'react'

export default function Child({parentToChild}) {
    return (
        <div>
            {parentToChild}
        </div>
    )
}
React の関数コンポーネント

ケース 2: クラスコンポーネントの場合は、this.props.parentToChild を使用します。

import React, { Component } from 'react'

export default class Child extends Component {
    render() {
        return (
            <div>
                {this.props.parentToChild}
            </div>
        )
    }
}
React のクラスコンポーネント

どちらのやり方でも同じ結果になります。

Screenshot-2021-06-06-132836

Click Parent ボタンをクリックすると、データが画面に出力されます。

import React from 'react'
import Child from './Child';
import { Button } from 'semantic-ui-react';
import { useState } from 'react';
import './App.css';

export default function Parent() {
  const [data, setData] = useState('');
  
  const parentToChild = () => {
    setData("This is data from Parent Component to the Child Component.");
  }
  return (
    <div className="App">
      <Child parentToChild={data}/>
      
      <div className="child">
        <Button primary onClick={() => parentToChild()}>Click Parent</Button>
      </div>
    </div>
  )
}

Parent コンポーネントの完成形のコードは上記の通りです。

子コンポーネントから親コンポーネントにデータを受け渡す方法

こちらは少し厄介です。

まず、Parent コンポーネント内に childToParent という名前の関数と、data という名前の空の state を作成します。

const [data, setData] = useState('');

const childToParent = () => {
   
}
Parent コンポーネント

次に、childToParent 関数を props として Child コンポーネントに受け渡します。

<Child childToParent={childToParent}/>
Child コンポーネントに childToParent を受け渡す

そして Child コンポーネント内で、この関数を props として受け取り、onClick イベントに割り当てます。

さらに、文字列または数値形式のデータを持つ state (data) を宣言します。

その data を parentToChild 関数に引数として渡します。

import React from 'react'
import { Button } from 'semantic-ui-react';

export default function Child({childToParent}) {
    const data = "This is data from Child Component to the Parent Component."
    return (
        <div>
            <Button primary onClick={() => childToParent(data)}>Click Child</Button>
        </div>
    )
}
Child コンポーネント

次に、Parent コンポーネント側で、このデータを childToParent 関数内で引数として受け取ります。

そして useState フックを使用して data を設定します。

import './App.css';
import { useState } from 'react';
import Child from './Child';

function Parent() {
  const [data, setData] = useState('');
  
  const childToParent = (childdata) => {
    setData(childdata);
  }

  return (
    <div className="App">
      <div>
        <Child/>
      </div>
    </div>
  );
}

export default Parent;
Parent コンポーネント

次に、return 文の中でその data 変数を表示します。

import './App.css';
import { useState } from 'react';
import Child from './Child';

function Parent() {
  const [data, setData] = useState('');
  
  const childToParent = (childdata) => {
    setData(childdata);
  }

  return (
    <div className="App">
     {data}
      <div>
        <Child childToParent={childToParent}/>
      </div>
    </div>
  );
}

export default Parent;
Parent コンポーネント

Click Child ボタンがクリックされると、子コンポーネントの data が親コンポーネントの data を上書きします。

Screenshot-2021-06-06-134803

これで、子コンポーネントから親コンポーネントへ、そして親コンポーネントから子コンポーネントへデータを受け渡す方法が分かりました。

onClick や OnChange のようなイベントを受け渡す

childToParent 関数の中で alert メソッドを呼び出すようにして、その関数を props として Child コンポーネントに受け渡します。

import './App.css';
import Child from './Child';

function Parent() {
  const childToParent = () => {
    alert("This is an alert from the Child Component")
  }

  return (
    <div className="App">
      <div className="child">
        <Child childToParent={childToParent}/>
      </div>
    </div>
  );
}

export default Parent;
Parent コンポーネント

そして Child コンポーネントで childToParent を props として受け取り、ボタンの onClick イベントに割り当てます。

import React from 'react'
import { Button } from 'semantic-ui-react';

export default function Child({childToParent}) {
    return (
        <div>
            <Button primary onClick={() => childToParent()}>Click Child</Button>
        </div>
    )
}
Child コンポーネント

Child コンポーネント内のボタンをクリックすると、Parent コンポーネント内の関数が呼び出され、次のようなアラートが表示されます。

Screenshot-2021-06-06-140405

以上です!

もっといろいろ実験したければ、GitHub にコードを公開していますのでご利用ください。

この記事は以上です。学習を楽しんでください。