概要
Reactアプリの作成を始めて最初に躓いた コンポーネント間でデータのやり取りをする基本 を自分なりに整理した。
背景と目的
前回、
Reactアプリの開発環境を整え、アプリを作り始めたが最初に強く感じたこととして
コンポーネント間でデータのやり取りをすることが、初学者にとって非常にハードルが高く感じる
がある。今までよくjQueryやベタのDOMを使って何もハードルを感じることなかったので、それとは対照的だ。そこで、ひとまずこのハードルを自分の中で乗り越えねばならないと思い、簡単なサンプルでもいいのでとにかくちゃんと動くものを整理してメモしておく。
詳細
1. やることを整理
ドロップダウンボックスの選択値を、divタグのinnerTextに表示する
といった非常に単純なこと。ここで、ドロップダウンボックスとdivタグは親子関係を想定しない。私が今知りたいのは、親子関係にない単純なコンポーネント同士である。、すなわち
// ドロップダウンボックスの関数コンポーネント function MyDropDown() { return ( <select></select> ); } // divの関数コンポーネント function MyDiv() { return ( <div></div> ); }
よくWeb上にあるサンプルは、以下のような親子関係にあるものばかり出てくるのだが、これではない。
function MyDropDown() { return ( <select></select> <div></div> ); }
2. App.js
いきなりだが、作成したものは以下。
import { useState, createRef } from 'react'; import { createContext, useContext } from 'react'; import './App.css'; const MyValue = createContext(1); const MyRef = createRef(); function MyDropDown() { const { myValue, setMyValue } = useContext(MyValue); function handleChange() { setMyValue(MyRef.current.value); } return ( <select onChange={handleChange} ref={MyRef} defaultValue={myValue}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> ); } function MyDiv() { const { myValue, setMyValue } = useContext(MyValue); return ( <div>{myValue}</div> ); } function App() { const [myValue, setMyValue] = useState(1); const value = { myValue, setMyValue }; return ( <div className="App"> <MyValue.Provider value={value}> <MyDropDown></MyDropDown> <MyDiv></MyDiv> </MyValue.Provider> </div> ); } export default App;
いくつかポイントを整理する。
2.1 Context
Reactにおいてコンポーネント間でデータを共有する仕組みとしてContextというものがある。これをApp.jsのグローバルで宣言しておく。
const MyValue = createContext(1);
このデータを使うには、コンポーネント内でuseContextを使って
const { myValue, setMyValue } = useContext(MyValue);
とする。
2.2 Ref
Refはコンポーネントの参照、すなわち今までidを振って参照したりしていたことに対応するReactでの仕組み。これもApp.jsのグローバルで宣言しておく。
const MyRef = createRef();
この参照を用いれば、ドロップダウンボックスの現在の選択値は、
MyRef.current.value
で参照できる。
2.3 Contextへの引き渡し
初めて見たときかなり戸惑ったが、とにかくstate機能を使って作成した変数をContextに紐づけるということ。 まず、以下のようにuseStateを使って状態管理用の変数myValueと値をセットする関数setMyValueを用意。
const [myValue, setMyValue] = useState(1); const value = { myValue, setMyValue };
そして、Context.Providerで共有したいコンポーネントを囲う。valueプロパティに、作成したmyValue、setMyValueを渡す。
<MyValue.Provider value={value}> <MyDropDown></MyDropDown> <MyDiv></MyDiv> </MyValue.Provider>
2.4 ドロップダウンボックス
現在のドロップダウンボックスの値が変化したら、MyRef.current.valueをMyValueに保存。
function MyDropDown() { const { myValue, setMyValue } = useContext(MyValue); function handleChange() { setMyValue(MyRef.current.value); } return ( <select onChange={handleChange} ref={MyRef} defaultValue={myValue}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> ); }
2.5 div
Contextから値をもらってinnerTextに与える。
function MyDiv() { const { myValue, setMyValue } = useContext(MyValue); return ( <div>{myValue}</div> ); }
3. 動作確認
動作確認するまでもないが、ドロップダウンボックスを操作するとdivのテキストがちゃんと変化する。
まとめと今後の課題
Reactアプリをやり始めて最初に感じたハードルを自分の中でクリアできてよかった。