工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

Reactで、コンポーネント間のデータやり取りをするための基本を整理して置く

概要

Reactアプリの作成を始めて最初に躓いた コンポーネント間でデータのやり取りをする基本 を自分なりに整理した。




背景と目的

前回、

dekuo-03.hatenablog.jp

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アプリをやり始めて最初に感じたハードルを自分の中でクリアできてよかった。