ReactでReduxやContextAPIを使わず、親コンポーネントに手続きを書かず、Providerも作らず、コンポーネント間通信する
コンポーネント間のデータのやりとり
Reactの序盤で障害となるのがコンポーネント間のデータのやりとりです。コンポーネントを超えてデータをやりとりしようとすると、親コンポーネントにstateを作って、値やdispatchを各コンポーネントに配る必要があります。もしくはContextAPI
やRedux
の利用という流れになっていくわけですが、導入時に書かなければいけないコードが増大するので、それなりの負担が待っています。
このあたりを簡単にする方法を紹介します。
※利用するに当たっては
yarn add -D @react-libraries/use-global-state
などのコマンドでパッケージをインストールする必要があります。
今回作ったコードは以下の場所にあります
https://github.com/SoraKumo001/use-global-state-sample01
使用例紹介 BMIを計算するプログラム
※Next.jsを使用していますが、useGlobalState自体は素のReactでも動作します
src/pages/index.tsx
import { useGlobalState } from '@react-libraries/use-global-state';
import React from 'react';
const Tall = () => {
const [value, setValue] = useGlobalState('tall', '170');
return (
<div>
Tall:
<input
value={value}
onChange={(e) => {
setValue(e.target.value);
}}
/>
</div>
);
};
const Weight = () => {
const [value, setValue] = useGlobalState('weight', '60');
return (
<div style={{ display: 'flex' }}>
Weight:
<input
value={value}
onChange={(e) => {
setValue(e.target.value);
}}
/>
</div>
);
};
const Bmi = () => {
const [tall] = useGlobalState<string>('tall');
const [weight] = useGlobalState<string>('weight');
return (
<div>
{isNaN(Number(tall)) || isNaN(Number(weight))
? 'Error'
: `BMI:${Math.floor((Number(weight) / Math.pow(Number(tall) / 100, 2)) * 100) / 100}`}
</div>
);
};
const Page = () => (
<>
<Bmi />
<Tall />
<Weight />
</>
);
export default Page;
useGlobalStateは名前の通りuseStateのグローバル版Hookです。コンポーネントを飛び越えてデータ共有が可能です。使用するに当たってはReduxやContextAPIにあるようなProvider相当のコンポーネントを上位に持つ必要はありません。いきなり書いていきなり使えます。イキナリ素敵です。
useGlobalStateは複数の場所で異なる初期値が設定されていた場合、最初に実行された初期値が採用されます。また、初期値無しを通った後に初期値ありを通った場合は、その初期値を利用してコンポーネントが再検証されます。
その他@react-libraries/use-global-state
にはmutate
関数を用意してあり、useGlobalStateの設置コンポーネント外からデータを設定することも可能です。データは送るけれど自分自身は再検証の対象にならないコンポーネントが作成可能です。
テスト実行時、保存データをクリアするためには@react-libraries/use-global-state
からreset
を取り出して実行します。
楽ちん
データやイベントのやりとりのために余計なコードを書かなくて済むのでとても楽ちんです。
Discussion