はじめに
タイトル通りReactで子コンポーネントから親コンポーネントを操作する方法についてまとめました.
既存記事はありますが,教材用として車輪を再発明します.
やりたいこと
Reactでは親コンポーネントから子コンポーネントに対して値を渡すことは容易です.また,適切にUseState
を使えば,親コンポーネントで値を更新した時コンポーネントの値も自動で更新されます.
しかし,同様の手順では子コンポーネント内の値更新を親コンポーネントに反映させることはできません.
この記事では,この動作の実現を目標とします.
コンポーネントの用意
ここではApp
コンポーネントからSubComponent
コンポーネントを呼び出す状況を想定します.つまりApp
で管理する値をSubComponent
コンポーネントから変更することが目標です.
環境はnpm create vite
で作成しました.
Appコンポーネント
とりあえずApp
コンポーネントに書かれているコードはほぼ消して,App
コンポーネントで管理する値を用意します.
import { useState } from "react";
import "./App.css";
function App() {
const [appValue, setAppValue] = useState(0);
return (
<>
<p>appValue = {appValue}</p>
</>
);
}
export default App;
SubComponentコンポーネント
SubComponent
コンポーネントでもそこで管理する値を用意します.また,その値を変えるためのボタンも配置します.
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です.
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
で定義し,setAppValue
はsetValue
という名前で受け取ることにしました.
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で呼び出していた関数を変更します.
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
を渡せるようにします.
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
上での値が変更できることを確認するために,useState
のsubValue
とsetSubValue
を定義していました.しかし,上でボタンのonClick
にコールバック関数として渡していたsetSubValue
はsetValue
に置き換えました.つまりsetSubValue
は不要です.SubComponent
コンポーネントでApp
コンポーネントと独立した値を管理する必要も無いので,subValue
と合わせて削除してしまいます.
-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
を変更して値を受け取れるようにします.
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
コンポーネントから値を渡せるようにします.
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;