1
0

Reactで子コンポーネントから親コンポーネントを操作するサンプル

Last updated at Posted at 2024-07-12

はじめに

タイトル通りReactで子コンポーネントから親コンポーネントを操作する方法についてまとめました.
既存記事はありますが,教材用として車輪を再発明します.

やりたいこと

Reactでは親コンポーネントから子コンポーネントに対して値を渡すことは容易です.また,適切にUseStateを使えば,親コンポーネントで値を更新した時コンポーネントの値も自動で更新されます.
しかし,同様の手順では子コンポーネント内の値更新を親コンポーネントに反映させることはできません.
この記事では,この動作の実現を目標とします.
コンポーネント間の値のやり取り

コンポーネントの用意

ここではAppコンポーネントからSubComponentコンポーネントを呼び出す状況を想定します.つまりAppで管理する値をSubComponentコンポーネントから変更することが目標です.
環境はnpm create viteで作成しました.

Appコンポーネント

とりあえずAppコンポーネントに書かれているコードはほぼ消して,Appコンポーネントで管理する値を用意します.

App.tsx
import { useState } from "react";
import "./App.css";

function App() {
  const [appValue, setAppValue] = useState(0);

  return (
    <>
      <p>appValue = {appValue}</p>
    </>
  );
}

export default App;

SubComponentコンポーネント

SubComponentコンポーネントでもそこで管理する値を用意します.また,その値を変えるためのボタンも配置します.

SubComponent.tsx
import { useState } from "react";
import "./App.css";

function SubComponent() {
  const [subValue, setSubValue] = useState(0);

  return (
    <>
      <p>subValue = {subValue}</p>
      <button onClick={() => setSubValue(0)}>subValue = 0</button>
      <button onClick={() => setSubValue(1)}>subValue = 1</button>
      <button onClick={() => setSubValue(2)}>subValue = 2</button>
    </>
  );
}

export default SubComponent;

SubComponentからAppコンポーネントの値を変更する

AppコンポーネントでSubComponentを呼び出す

1行加えるだけでOKです.

App.tsx
import { useState } from "react";
import "./App.css";

function App() {
  const [appValue, setAppValue] = useState(0);

  return (
    <>
      <p>appValue = {appValue}</p>
+     <SubComponent />
    </>
  );
}

export default App;

これで画面は以下のようになります.
現在の画面

コールバック関数の定義

SubComponentからAppコンポーネントの値を変更するために,AppコンポーネントのsetState(今回はsetAppValue)を受け取れるようにします.このときsetAppValueを引数として受け取ります.ある関数Aに引数として渡される関数Bのことをコールバック関数といいます.
コールバック関数の型はinterfaceで定義し,setAppValuesetValueという名前で受け取ることにしました.

SubComponent.tsx
import { useState } from "react";
import "./App.css";

+interface SubComponentProps {
+  setValue: (value: number) => void;
+}

+ function SubComponent({ setValue }: SubComponentProps) {
  const [subValue, setSubValue] = useState(0);

  return (
    <>
      <p>subValue = {subValue}</p>
      <button onClick={() => setSubValue(0)}>subValue = 0</button>
      <button onClick={() => setSubValue(1)}>subValue = 1</button>
      <button onClick={() => setSubValue(2)}>subValue = 2</button>
    </>
  );
}

export default SubComponent;

コールバック関数の使用

受け取ったsetValueを使うために,buttonで呼び出していた関数を変更します.

SubComponent.tsx
import { useState } from "react";
import "./App.css";

interface SubComponentProps {
  setValue: (value: number) => void;
}

function SubComponent({ setValue }: SubComponentProps) {
  const [subValue, setSubValue] = useState(0);

  return (
    <>
      <p>subValue = {subValue}</p>
+      <button onClick={() => setSubValue(0)}>setValue = 0</button>
+      <button onClick={() => setSubValue(1)}>setValue = 1</button>
+      <button onClick={() => setSubValue(2)}>setValue = 2</button>
    </>
  );
}

export default SubComponent;

これでSubComponentコンポーネントからの準備は終わりました.
次に,AppコンポーネントからSubComponentコンポーネントにsetValueを渡せるようにします.

App.tsx
import { useState } from "react";
import "./App.css";
import SubComponent from "./SubComponent";

function App() {
  const [appValue, setAppValue] = useState(0);

  return (
    <>
      <p>appValue = {appValue}</p>
+     <SubComponent setValue={setAppValue} />
    </>
  );
}

export default App;

これで下図のようにSubComponentのボタン操作でAppコンポーネントの値を変更できるようになりました.
値の変更ができるようになった時の図

値の受取

準備段階ではSubComponent上での値が変更できることを確認するために,useStatesubValuesetSubValueを定義していました.しかし,上でボタンのonClickにコールバック関数として渡していたsetSubValuesetValueに置き換えました.つまりsetSubValueは不要です.SubComponentコンポーネントでAppコンポーネントと独立した値を管理する必要も無いので,subValueと合わせて削除してしまいます.

SubComponent.tsx
-import { useState } from "react";
import "./App.css";

interface SubComponentProps {
  setValue: (value: number) => void;
}

function SubComponent({ setValue }: SubComponentProps) {
- const [subValue, setSubValue] = useState(0);

  return (
    <>
+     <p>subValue = {}</p>
      <button onClick={() => setValue(0)}>subValue = 0</button>
      <button onClick={() => setValue(1)}>subValue = 1</button>
      <button onClick={() => setValue(2)}>subValue = 2</button>
    </>
  );
}

export default SubComponent;

SubComponentコンポーネント上でもAppコンポーネントで管理する値を表示したくなる場合もあるかもしれません.そのときはinterfaceを変更して値を受け取れるようにします.

SubComponent.tsx
import "./App.css";

interface SubComponentProps {
  setValue: (value: number) => void;
+ value: number;
}

+function SubComponent({ setValue, value }: SubComponentProps) {

  return (
    <>
+     <p>subValue = {value}</p>
      <button onClick={() => setValue(0)}>subValue = 0</button>
      <button onClick={() => setValue(1)}>subValue = 1</button>
      <button onClick={() => setValue(2)}>subValue = 2</button>
    </>
  );
}

export default SubComponent;

SubComponentコンポーネントの変更に合わせて,Appコンポーネントから値を渡せるようにします.

App.tsx
import { useState } from "react";
import "./App.css";
import SubComponent from "./SubComponent";

function App() {
  const [appValue, setAppValue] = useState(0);

  return (
    <>
      <p>appValue = {appValue}</p>
+     <SubComponent setValue={setAppValue} value={appValue} />
    </>
  );
}

export default App;

このようにどちらの値も連動して変化するようになりました.
値を渡せるようになった時の図

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0