Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
15
Help us understand the problem. What is going on with this article?
@jima-r20

React HooksのuseEffectで関数コンポーネントにライフサイクルを持たせる

目次

はじめに

この記事では、React 16.8で導入されたHooksの機能の一つで、関数コンポーネントにライフサイクルメソッドを記述することのできるuseEffectについてまとめています。現在ReactやHooksについて学習中の方の一助となれば幸いです。

前提条件

  • Reactについて基本的な部分を理解している

環境

導入 version
react 16.13.1

useEffectとは

useEffectは簡単にいうと、関数コンポーネントにライフサイクルメソッドを持たせるための機能です。
Hooksが導入される以前のReactでは、コンポーネントにライフサイクルメソッドを持たせるためにはクラスコンポーネントで記述する必要がありました。そのためはじめは関数コンポーネントで記述していたコンポーネントにライフサイクルイベントを追加する必要が出てきたときにわざわざクラスコンポーネントに変換しなければなりませんでした。このような問題を解決する手段としてuseEffectが利用できます。
useEffectでは、クラスコンポーネントで利用していたライフサイクルメソッドであるcomponentDidMountcomponentDidUpdatecomponentWillUnmountを1種類の関数で扱うことができます。

useEffect.001.png

またHooksがないときにはクラスコンポーネントと関数コンポーネントが混在していましたが、useEffectuseStateなどのHooksの機能を利用することで全てを関数コンポーネントで記述できるため、コード全体の可読性を高めることもできるでしょう。

useEffectが呼び出されるタイミング

はじめに、関数コンポーネントがレンダリングおよび再レンダリングされるタイミングについて説明します。

初回レンダリングのタイミング

  • 関数コンポーネントがJSXとして読み込まれたとき

再レンダリングのタイミング

  • 親コンポーネントが再レンダリングされたとき
  • 受け取っているpropsに変化が生じたとき
  • 同コンポーネント内でuseStateを用いて定義している変数に変化が生じたとき

など

useEffectはこのようなレンダリングのタイミングで、自身で指定した任意の変数に変化が生じたときにコールバックとして記述した処理を実行します。

useEffectの使い方

では実際にuseEffectの使い方について見ていきましょう。useEffectの書き方の違いで呼び出される条件が変化するので、しっかり抑えておきましょう。

useEffectを利用するための基本

useEffectのインポート
何か別のライブラリを読み込む必要はなく、Reactからインポートして使用できます。

import React, { useEffect } from 'react';  // ここでuseEffectをインポートする

useEffectの基本構文
useEffectには第一引数としてコールバック関数、第二引数として任意の変数を格納する配列を記述します。
なお第二引数は省略可能です。

useEffect(() => {
  // 処理
}, [/* 任意の変数 */]);

以上がuseEffectを利用するための基本となります。

次に使用目的ごとに実際の記述方法について見ていきます。

レンダリングされるタイミングで毎回実行する

初回レンダリング時および再レンダリングに毎回useEffectに渡したコールバック関数を実行する方法について説明します。
レンダリング時に毎回実行する方法は、useEffectの第二引数を省略することです。

App.js
import React, { useEffect } from 'react';

const App = () => {
  useEffect(() => {
    // 処理
  });  // 第二引数を省略

  return (
    // JSX
  );
};

※ ただし第二引数を省略し、レンダリング時に毎回実行するようにすると何らかの原因で無限ループに陥る可能性があるので極力このような記述はしない方がいいでしょう。

初回レンダリング時のみ実行する

クラスコンポーネントのライフサイクルメソッドのcomponentDidMountのように初回レンダリング時にのみ処理を実行したいときは、第二引数の配列を空にして記述します。

App.js
import React, { useEffect } from 'react';

const App = () => {
  useEffect(() => {
    // 処理
  }, []);  // 第二引数の配列を空にする

  return (
    // JSX
  );
};

任意の変数が変化したときのみ実行する

関数コンポーネント内で使用している変数に変化が生じたときに、useEffectに渡したコールバック関数を実行したいときには、第二引数の配列にその変数を指定します。
少し具体的な例として、ボタンを押すと数値が加算されるカウンターを作成してみます。

Counter.js
import React, { useState, useEffect } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('useEffect!!')
  }, [count]);  // 第二引数の配列に任意の変数を指定(ここではcountが変化した時のみ実行されるようにしている)

  return (
    <div>
      {count}
      <button onClick={() => setCount((prevCount) => prevCount + 1)}>
        ADD 1
      </button>
    </div>
  );
};

簡単な例ではありますが、このように記述することでcountが変化したときにのみuseEffectに渡しているコールバック関数が実行されます。

以上がuseEffectの基本的な使い方です。

useEffectで非同期処理をする

useEffect内の() => {}には非同期関数またはpromiseを返す関数を記述することができません。
ではどのようにuseEffectで非同期処理を行えばいいのでしょうか。
結論としては2通りの方法があります。

  • 方法1

 useEffectの外で別の関数を定義し、その関数をuseEffectで呼び出す

  • 方法2

 async, awaitを利用して特殊な記述をする

方法1については何となくイメージができると思いますので、ここでは方法2について詳しい記述方法を紹介します。

import React, { useEffect } from 'react';

const App = () => {

  useEffect(() => {
    (async () => {
      await // 処理
    })();
  }, [/* 任意の変数 */]);

  return (
    // JSX
  );
};

少し見慣れない書き方かもしれませんがこのように記述することで、useEffectで非同期処理を行うことができます。

誤って、

// BAD example!!
useEffect(async () => {
  await //  処理
}, [/* */])

としないように注意しましょう。

まとめ

簡単ではありますが、useEffectについての説明は以上になります。
まとめると、

  • useEffect関数コンポーネントでライフサイクルメソッドを持たせるための機能
  • クラスコンポーネントで利用していたライフサイクルメソッドを一つの関数で表現できる
  • 記述の仕方で実行タイミングが変わる
  • 非同期処理させるためには注意が必要

といった感じです。

実際にはuseEffectの使い方としてはまだまだたくさんありますが、基本中の基本はこの記事にまとめてあることなのでしっかり抑えていただければと思います。
今後アプリケーションを作成する際に、適した使い方をしていきましょう。

また参考資料に記載しているリンク先ではさらに詳しい使い方や解説をしてくれていますので、是非みて見てください。

参考資料

15
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
jima-r20
現在学習中の言語に関することや気になったことについて備忘録的にまとめた記事を投稿しています。同じように勉強中の人の一助となれば幸いです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
15
Help us understand the problem. What is going on with this article?