その他

「ReactはただのUIフレームワークである」ということをもっと伝えたい

The smug face of the author その他
The smug face of the author
この記事は約6分で読めます。

こんにちは。株式会社インプルの加納です。

Reactの経験が増えるにつれ、人に教える場面も増えました。色々なご質問をいただくのですが「難しく考えすぎている」ケースも多い印象です。

React はその公式ドキュメントのトップにもあるように「UIを構築するための」ライブラリです。ただUIが構築できればそれでOKで、それ以外は普通のJavaScriptです。

Reactのトップページ
  • React始めたばかりで、ちょっと難しいな〜と思っている方は、本稿がシンプルに考えるための助けになるかも知れません。
  • Reactのご経験豊富な方には、特に役に立たない記事です。ご了承ください。

State がメインコンセプト

シンプルに「State(状態)」がReactのメインとなる部分です。それ以外はオマケと思っても最初は差し支えないでしょう。実際、Reactのトップページにも「JSXは必須ではない」と書いてあります。

わざわざ太字で書いてある

コンポーネントが状態をもつ

では、そのStateとはなんでしょうか。これはコンポーネントの状態をUIに反映するためのものです。

押すと数字が増えるボタン

押すと数字が書き変わるボタンがあります。

const LikeButton = () => {
  const [count, setCount] = React.useState(0);
  const onClick = () => setCount((count) => count + 1);
  
  return (
    <button onClick={onClick}>
      {count}
    </button>
  );
}

Stateを更新する = 画面を更新する

重要なポイントは1つだけです。「Stateを書き換える」と「画面が書き変わる」ことです。この画面の更新を実現するために、 Stateを書き換える専用の関数が用意されます。

上記のコードで言うと `setCount` です。この関数が実行されると `LikeButton`関数が再度実行されます。ただし、 Stateの値だけは、`LikeButton`関数が再度実行されても保持されます。

重要なのでまとめます。

  • setState 関数は、そのコンポーネント関数自体を再度実行する
  • その際、Stateの値だけは保持される(逆にいうとその他の変数は初期化される)

LikeButton`関数が再度実行された時、countの値だけは +1されています。これによって、画面に表示される数字だけが書き変わったように見えるのです。


    <button onClick={onClick}>
      {count}
    </button>

useEffect (副作用フック)とは

こうして考えると、Reactにおける「Effect(作用)」がなにを指すのかが明らかになります。作用とは「画面(UI)の更新」のことです。なんと言ってもReactはUIフレームワークです。そのメイン作用は画面の更新以外にあり得ません。

画面の更新時に(副作用として)コールバックを実行する

const LikeButton = () => {
  const [count, setCount] = React.useState(0);
  const onClick = () => setCount((count) => count + 1);

  useEffect(() => {
    console.log("ボタンが押されるたびに実行されます");
  }, [count]);

  return <button onClick={onClick}>{count}</button>;
};

上記の useEffect は 以下の場合にコールバックを実行します。

  1. 画面の初期表示時
  2. count 変数 の更新時

両方とも、「画面の更新時」です。

よくある1回だけの useEffect

const Button = () => {

  useEffect(() => {
    console.log("最初に1回だけ実行したいです!");
  }, []);

  return <button />;
};

初期表示時だけ実行する目的で、空配列に依存した `useEffect` があります。画面の更新時に1回コールバックを実行して、その後は実行されません。

よくあるミス: 全部Stateにする

初学者の方にここまで説明すると、単一のコンポーネントで管理するStateが激減します。以下のようなコンポーネントを書いてエラーになっている…React学習時の「あるある」かと思います。

const LikeButton = () => {
  const [count, setCount] = React.useState(0);
  const [doubledCount, setDoubledCount] = React.useState(0);
  const onClick = () => setCount((count) => count + 1);

  useEffect(() => {
    console.log("ボタンが押されるたびに実行されます");
    setDoubledCount(count * 2);
  }, [count]);

  return <button onClick={onClick}>{doubledCount}</button>;
};

やりたいことは、数字を2倍にして表示することです。そのために専用のStateとして `doubledCount`を用意しています。ところが本来 State は count だけで良いわけです。doubledCountは普通の変数で十分です。

const LikeButton = () => {
  const [count, setCount] = React.useState(0);
  const doubledCount = count * 2;
  
  const onClick = () => setCount((count) => count + 1);

  return <button onClick={onClick}>{doubledCount}</button>;
};

useEffect も必要ありません。

setCount 関数は、`LikeButton`関数を再度実行します。 const による 変数 `doubledCount` の宣言ももちろん再度行われます。`count` はクリック数を保持していますから、ちゃんと2倍された数字が画面に表示されます。

まとめ

難しく考えなくてOK!Stateを利用することで手軽に画面を更新するためのライブラリ。

  • React は ただのUIライブラリ
  • Stateを更新 = 画面を更新 ← これがメインの役割

setState がコンポーネント関数を再度実行することが意識できると、Stateの量やその他のフックもかなり減ります。または、メモ化や ref を使用した最適化など、できることがグッと増えるでしょう。

初心者の方におすすめの記事はコチラ