React で呼び出し元の部品にデータを渡すには?

記事
IT・テクノロジー

React で呼び出し元の部品にデータを渡すには?

Veu の場合、呼び出し元(親)の部品に、呼び出される(子)の部品からデータを渡す機能があります。React の場合にも似たような機能を実装できますが、考え方が少し違っています。この記事では、React で「子」から「親」にデータを渡す例を紹介します。


Vue の場合は?

Vue の場合は、公式チュートリアル(英語版)のステップ13で紹介されているように、「_emit_」を使うと、「子」の部品から「親」の部品にデータを送る事ができます。

<script>
export default {
  emits: ["response"],
  created() {
    this.$emit("response", "hello from child");
  },
};
</script>
この場合、「_emits_」で定義している、「_response_」という名前で、「_this.$emit('response', 'XXXX')_」を使うと、データを「親」の部品に送る事ができます。

この例では、「hello from child」というデータを「親」に送っています。

「親」の部品では、最初は「No child msg yet」というデータをセットしておいて、データが送られてきた場合には、送られてきたデータに更新するという処理を行なっています。

React ではどうするか?

実は、React の場合、基本的な考えとして、「子」の部品から「親」の部品にデータを送るような Vue の機能はサポートされていません。基本的に、データのやり取りは「親」の部品から「子」の部品への一方通行になっています。

そう考えると、Vue の方が機能が多く、優れているように思いがちですが、同じ様な機能は React でも実現可能です。この場合、「親」の部品で設定した、「No child msg yet」という表示データを、「子」の部品で、「hello from child」に更新するという処理です。

React で処理する場合には、「子」の部品から「親」の部品にデータを送るのではなく、「子」の部品で、「親」のステート管理しているデータの更新を行うという方法で同じ機能を実現しています。

実際に実装例を先に紹介します。

import React, { SetStateAction, useState } from "react";
import Step13Child from "./step13Child";
import "./styles/step13.css";
export default function Step13(): JSX.Element {
  const [childMsg, setChildMsg]: [
    string,
    React.Dispatch<SetStateAction<string>>
  ] = useState("No child msg yet");
  return (
    <React.Fragment>
      <div>
        <Step13Child report={setChildMsg} />
        <p>{childMsg}</p>
      </div>
    </React.Fragment>
  );
}
ステート管理している変数「_childMsg_」を更新する関数「_setChildMsg()_」を「子」の部品に渡して、「子」の部品側でデータの更新をできるようにするという仕組みです。

「子」の部品側では、この受け取った関数を使って「親」の表示データを更新します。

import React, { SetStateAction, useEffect } from "react";

interface IProps {
  report: React.Dispatch<SetStateAction<string>>;
}
export default function Step13Child(props: IProps): JSX.Element {
  useEffect((): void => {
    props.report("hello from child");
  });
  return (
    <React.Fragment>
      <div>
        <h2>Child component</h2>
      </div>
    </React.Fragment>
  );
}
この例では、Vue の公式チュートリアル(英語版)のステップ13とほぼ同じように、「子」の部品側のデータを使って、「親」の表示を更新しています。見た目の機能は Vue のステップ13とこの上に上げた処理は同じように動作します。

考え方の違い
Vue の場合では、「子」の部品から「親」の部品にデータを送って、「親」の部品側で、表示に利用するデータの更新を行うという方法で処理しています。今回の、React の例では、「親」の部品の表示に利用するデータを更新する関数を「子」の部品に渡して、「子」の部品側で、「親」の表示データを更新しています。

結果的に、「子」のデータを使って、「親」の表示データを更新しているので、見かけ上は同じになっています。つまり、React のデータの受け渡しは一方通行ですが、データを処理する関数を渡すことで「子」からデータを「親」に送らずに同じ機能を実現しているという事になります。

要は、Vue と React の基本的な設計思想の違いです。

プログラミングの実装では、同じ様な機能を色々な違った方法を使って実現できます。React と Vue の実装方法の違いもその一つという事になります。

React のデータのやり取りは一方通行
React の場合には、データ(関数なども含めて)のやり取りは、基本的に「親」から「子」の一方通行と考えてください。データを「子」から「親」に渡せない代わりに、データを処理する「関数」を「親」から「子」に渡すことで、データを「親」に渡せなくても、同じ様な機能が実現できるように設計します。

通常の実装ではこの方法で十分です。さらに複雑なデータのやり取りが必要な場合には、データを一括管理する方法を利用します。Redux などの利用がその例です。一見、「子」から「親」にデータが渡せないと不便な感じがしますが、実は大きな違いではありません。

まとめ
今回は、「子」のデータを「親」の部品で利用する例を紹介しました。 Vue の場合は、「子」から「親」にデータを渡すという形で紹介されていますが、実際には、「子」のデータを「親」の表示に反映させる機能という方が一般的な表現です。

そう考えた場合、直接データを「子」から「親」に渡せなくても、同じ様な機能が実現できます。

React と Vue では設計思想が少し違っているので、機能を比べると React が劣っている様に見える場合がありますが、機能的には大きな違いはありません。

それぞれの、フレームワークでの機能の実装の方法をよく理解しておく事が重要になります。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す