Reactの基礎 その5:React hooks その2 useEffect()

新しい現場で本格的にReactを触ることになったのでReactについて学んだことを備忘録として記事にしていきます。
いくつかの記事にわけてReactでステートメントを保持・管理するための機能であるReact hooksについてまとめていきます。

サンプルコードについて

サンプルコードはこちらにあります。
記事ごとにコミットログで分けてあるので該当するコミットをご覧ください。

React hooksとは

React hooksとは関数コンポーネント内の状態やライフサイクルなどのReactの機能を「フック」するために用意されている機能群の総称です。
React hooksを副作用や状態管理の実行などを行うことができ、その用途に合わせて様々な種類のhooksを利用することができます。
React hooksはuse〇〇と名付けられており、〇〇の部分に利用する機能を表す単語が入ります。
React hooksはあらかじめ用意されている機能が多数あり、いくつかの記事に分けて紹介していきたいと思います。
今回はReact hooksの中でも副作用フックを扱うuseEffect()を紹介します。

useEffect()とは

今回は副作用フックを扱うuseEffect()についてまとめていきます。
副作用とは、レンダリングに直接関係しない処理のことで、データのフェッチや手動でのDOMの更新、ログの記録などが含まれます。
例えば、初期表示の際のデータを取得する処理やユーザーによる状態の変更が発生した際の表示の更新などです。
useEffect()は第一引数に副作用として実行する処理、第二引数に依存配列を渡すことで副作用の設定をします。

import { useEffect } from 'react';

useEffect(() => { 副作用として実行する処理 }, [依存配列]);

useEffect()に第一引数で渡された副作用は第二引数の依存配列の要素のいずれかが変更された際に実行されます。
依存配列を空で渡した場合、コンポーネントのマウント時、つまり最初に一回だけ副作用が実行されます。
これは、初期表示を行うための処理などでよく利用されます。

useEffect()の利用例

初期表示でデータをフェッチする利用例を見ていきます。
TODOのカードのデータを初期表示時にフェッチします。

ボディコンポーネント内のコードが以下のようになっています。

import React from "react";
import Card from "./Card";

const { useState, useEffect } = React;

function Body() {
  // 本来はDBなどから取得してきますが、今回はfetchCards()でカードをフェッチしている体でコードを書いています。
  const initialCards = [
    {
      id: '1',
      content: 'Study English',
      status: 'Not Ready',
    },
    {
      id: '2',
      content: 'Study React',
      status: 'Ready',
    },
    {
      id: '3',
      content: 'Clean Room',
      status: 'Compleated',
    },
  ]

  // 見せかけのカードフェッチ関数
  const fetchCards = () => {
    return initalCards;
  };

  const toggleStatus = (status) => {
    switch(status) {
      case 'Not Ready':
        return 'Ready';
      case 'Ready':
        return 'Compleated';
      case 'Compleated':
        return 'Not Ready';
      default:
        throw new Error('無効なステータスです');
    }
  }

  // ステータスボタンが押された時の処理
  const handleToggleStatus = (id) => {
    const newCards = cards.map(c => {
      if (c.id === id) {
        return {
          ...c,
          status: toggleStatus(c.status),
        };
      } else {
        return c;
      }
    });
    setCards(newCards);
  }

  // useState()でTODOカード一覧の状態を管理する
  const [cards, setCards] = useState([]);

  // useEffect()でTODOカード一覧の初期値を取得し初期表示させる
  useEffect(() => {
    const cards = fetchCards();
    setCards(cards);
  }, []);

  return (
    <div className='body'>
      {cards.map(c => {
        return (
          <Card
            card={c}
            toggleStatus={handleToggleStatus}
          />
        )
      })}
    </div>
  )
}

export default Body

カードコンポーネントは以下のようになっています。

import React from "react";

function Card({ card, toggleStatus }) {
  return (
    <div className='card'>
      <div className="todoIcon">✔︎</div>
      <div className='todocontent'>{card.content}</div>
      <div className="todoStatus">
        <span>status:</span>
        <button
          className="statusButton"
          onClick={() => toggleStatus(card.id)}
        >
          {card.status}
        </button>
      </div>
    </div>
  )
}

export default Card;

useEffect()で初期表示時にフェッチしたTODOカードのデータをuseState()で定義したTODOカードのステートに設定してます。
map()関数でTODOカードのリストを1つずつ取り出し、カードコンポーネントに渡すことで全てのカードを表示をさせています。
今回のサンプルコードでは、コード内に定義している初期値をそのまま返すだけの見せかけのフェッチ関数を作成していますが、本来であればDBやローカルストレージから取得して行います。
このように、初期表示時にのみ副作用を実行させる場合は、依存配列を空にして渡します。

まとめ

今回はReact hooksの第二弾としてuseEffect()を紹介しました。
前回紹介したuseState()続いて利用されることの多いhooksだと思います。
副作用など言葉だけでは感覚がつかみにくいものでもあると思うので、実際に自分でコードを書いてみてどのように動作するのかを見てみるのが良いと思います。
ここまで読んでいただき、ありがとうございました。
それでは、また。

Reactの基礎の過去の記事はこちら。

キョウタコの技術日記

新しい現場で本格的にReactを触ることになったのでReactについて学んだことを備忘録として記事にしていきます。何回か…

キョウタコの技術日記

新しい現場で本格的にReactを触ることになったのでReactについて学んだことを備忘録として記事にしていきます。何回か…

キョウタコの技術日記

新しい現場で本格的にReactを触ることになったのでReactについて学んだことを備忘録として記事にしていきます。今回は…

キョウタコの技術日記

今回からいくつかの記事にわけてReactでステートメントを保持・管理するための機能であるReact hooksについてま…