Reactフックの解説と使用例のまとめ

今日は、React.jsのHooksについて初めて学ぶ初心者の方々向けに、詳しい解説とまとめを提供します。

以下では、簡潔かつ分かりやすく説明します。

Hooksとは

React Hooksは、Reactライブラリの機能の一つであり、関数コンポーネント内で状態管理や副作用を行うための手段です。これにより、クラスコンポーネントに依存せず、よりシンプルで再利用可能なコンポーネントを作成することができます。

Hooksには多くの便利なフックがあります。

React Hooksは、クラスコンポーネントに比べてよりシンプルで直感的なコードを書くことができるため、初心者にとっても学びやすいです。Hooksを使用することで、Reactのパワフルな機能を活用しながら、効率的でメンテナンス性の高いアプリケーションを構築することができます。

useState()

状態の管理にuseStateフックを利用します。

useStateフックは、Reactコンポーネント内で状態を管理するために使用されるものです。状態とは、コンポーネント内で変化する値やデータのことです。useStateフックを使用することで、状態を作成し、その状態を更新するための関数を提供することができます。

以下に、カウンターコンポーネントの例を示します。

import React, { useState } from 'react';

const Counter = () => {
  // useStateフックを使用してcountという状態を作成し、初期値を0に設定します
  const [count, setCount] = useState(0);

  // カウントを増やす関数
  const increment = () => {
    setCount(count + 1); // setCountを使ってcountの値を更新します
  };

  // カウントを減らす関数
  const decrement = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};

export default Counter;

上記の例では、useStateフックを使用してcountという状態を作成し、初期値を0に設定しています。

setCountは、countの値を更新するための関数です。

increment関数とdecrement関数は、ボタンがクリックされた時に呼び出され、それぞれsetCountを使用してcountの値を増減させています。

このように、useStateフックを使うことで、コンポーネント内で簡単に状態を作成し、その状態を更新することができます。また、useStateフックは関数コンポーネント内で使用されるため、よりシンプルで直感的なコードを書くことができます。

useEffect()

useEffectフックは、Reactコンポーネント内で副作用を扱うために使用されるものです。

副作用とは、データのフェッチ、DOMの変更、イベントの購読など、コンポーネントレンダリングとは直接関係のない操作のことです。useEffectフックを使用することで、コンポーネントがマウントされた後や特定の状態が変更された後に実行される関数を指定することができます。

以下に、非同期処理の単純な例を示します。

import React, { useState, useEffect } from 'react';

const AsyncExample = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        setData(data);
      } catch (error) {
        console.log('Error fetching data:', error);
      }
    };

    fetchData(); // fetchData関数を実行します

    return () => {
      // コンポーネントがアンマウントされる時に実行されるクリーンアップ関数
      // 例えば、タイマーのクリアやイベントリスナーの削除などを行います
      // この例では特にクリーンアップする処理はありません
    };
  }, []); // 第二引数の空配列は、コンポーネントのマウント時にのみ実行されることを意味します

  return (
    <div>
      {data ? (
        <p>Data loaded: {data}</p>
      ) : (
        <p>Loading data...</p>
      )}
    </div>
  );
};

export default AsyncExample;

上記の例では、useEffectフックを使用して非同期処理を実行しています。

useEffectのコールバック関数内で、fetchDataという非同期関数を定義し、APIからデータをフェッチしています。データのフェッチが完了したら、setData関数を使用して取得したデータを更新します。

また、第二引数の空の配列([ ])を指定しています。

これは、useEffectのコールバック関数がコンポーネントのマウント時にのみ実行され、更新時には実行されないことを意味します。つまり、この例では初回のマウント時にのみ非同期処理が実行されます。

最後に、条件に応じてデータの読み込み中の表示や読み込み完了時の表示を行っています。

このように、useEffectフックを使用することで、コンポーネントのライフサイクルや状態の変化に応じた非同期処理を実行すること

useContext()

useContextフックは、Reactコンポーネント間でデータを共有するために使用されるものです。一つのコンポーネントで作成された状態や関数を、他のコンポーネントでも利用したい場合に便利です。

以下に、単純な例を示します。

import React, { useContext } from 'react';

// コンテキストの作成
const MyContext = React.createContext();

// 親コンポーネント
const ParentComponent = () => {
  const data = "Hello, World!";

  return (
    <MyContext.Provider value={data}>
      <ChildComponent />
    </MyContext.Provider>
  );
};

// 子コンポーネント
const ChildComponent = () => {
  const data = useContext(MyContext);

  return <p>{data}</p>;
};

export default ParentComponent;

上記の例では、まずMyContextというコンテキストを作成しています。親コンポーネントであるParentComponent内で、dataという値を定義しています。

MyContext.Providerを使って、datavalueとして提供します。ChildComponentでは、useContextフックを使用してMyContextからデータを受け取り、表示します。

この例では、ChildComponentParentComponentから提供されたデータを直接利用できます。useContextフックによって、コンテキストの値を簡単に取得することができます。

このように、useContextフックを使用することで、コンポーネント間でデータを共有することができます。コンテキストは、アプリケーションの状態やテーマ、ユーザー認証など、共有する必要があるデータを効果的に管理するための強力なツールです。

useReducer()

useReducerフックは、Reactコンポーネント内で状態管理を行うためのものです。useStateフックと同様に状態を管理しますが、複雑な状態の更新やアクションの処理に適しています。

以下に、単純な例を示します。

import React, { useReducer } from 'react';

// 初期状態とアクションを定義
const initialState = 0;

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return state + 1;
    case 'decrement':
      return state - 1;
    case 'reset':
      return initialState;
    default:
      throw new Error('Unknown action type');
  }
};

// コンポーネント
const Counter = () => {
  const [count, dispatch] = useReducer(reducer, initialState);

  const increment = () => {
    dispatch({ type: 'increment' });
  };

  const decrement = () => {
    dispatch({ type: 'decrement' });
  };

  const reset = () => {
    dispatch({ type: 'reset' });
  };

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
};

export default Counter;

上記の例では、useReducerフックを使用して状態管理を行っています。

initialStateという初期状態を定義し、reducerという関数を作成します。

reducer関数は、現在の状態とアクションを受け取り、新しい状態を返します。

Counterコンポーネント内で、useReducerフックを使用してcountdispatchを取得します。

countは現在の状態を表し、dispatchはアクションを発行するための関数です。

increment関数、decrement関数、reset関数では、dispatch関数を使用して適切なアクションを発行します。

最終的に、countの値を表示し、ボタンをクリックすることで状態を変更することができます。

このように、useReducerフックを使用することで、状態とアクションを組み合わせて複雑な状態管理を行うことができます。特に、状態の変更が複数のアクションに依存する場合や、状態遷移がより複雑な場合に有用です。

つまり、大規模なアプリケーションでの状態管理向けです。

useMemo()

useMemoフックは、計算コストの高い処理や値のメモ化を行うために使用されるものです。処理の結果をキャッシュし、同じ引数での再計算を避けることができます。

以下に、単純な例を示します。

import React, { useMemo, useState } from 'react';

// 長い文字列の反転を行う関数
const reverseString = (str) => {
  console.log('Reversing string...');
  return str.split('').reverse().join('');
};

// コンポーネント
const StringReverser = () => {
  const [input, setInput] = useState('');
  
  // useMemoフックを使って計算結果をキャッシュする
  const reversedString = useMemo(() => {
    return reverseString(input);
  }, [input]);

  const handleChange = (e) => {
    setInput(e.target.value);
  };

  return (
    <div>
      <input type="text" value={input} onChange={handleChange} />
      <p>Reversed string: {reversedString}</p>
    </div>
  );
};

export default StringReverser;

上記の例では、StringReverserコンポーネントで入力値を受け取り、その入力値の反転を表示します。reverseString関数は長い文字列の反転を行う処理です。

useMemoフックを使用して、入力値が変更された時にのみreverseString関数を実行し、その結果をキャッシュします。入力値が変更されない限り、キャッシュされた結果を再利用します。これにより、入力値が変更されるたびにreverseString関数が実行されるのを防ぎ、パフォーマンスを向上させます。

このように、useMemoフックを使用することで、計算コストの高い処理や関数の結果をキャッシュし、無駄な再計算を避けることができます。メモ化によって、アプリケーションのレンダリングパフォーマンスを向上させることができます。

useCallback()

useCallbackフックは、Reactコンポーネント内でメモ化されたコールバック関数を作成するために使用されるものです。関数をキャッシュし、同じインスタンスを再利用することでパフォーマンスの向上が期待できます。

以下に、単純な例を示します。

import React, { useCallback, useState } from 'react';

// 遅延実行される関数
const delayedFunction = () => {
  console.log('Function executed after 2 seconds');
};

// コンポーネント
const FunctionExecutor = () => {
  const [count, setCount] = useState(0);

  // useCallbackフックを使ってコールバック関数をメモ化する
  const handleButtonClick = useCallback(() => {
    setTimeout(delayedFunction, 2000);
  }, []);

  const incrementCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={incrementCount}>Increment</button>
      <button onClick={handleButtonClick}>Execute Function</button>
    </div>
  );
};

export default FunctionExecutor;

上記の例では、FunctionExecutorコンポーネント内でカウンターの値を追跡し、ボタンがクリックされると遅延実行される関数を実行します。

useCallbackフックを使用して、handleButtonClickというコールバック関数をメモ化します。

第二引数の空配列([ ])は、このコールバック関数が再生成される条件を指定しています。空の配列を指定することで、コンポーネントのマウント時にのみ一度だけ関数が生成され、以降は同じインスタンスが再利用されます。

これにより、handleButtonClickが再生成されるたびに遅延実行される関数が生成されるのを防ぎ、パフォーマンスを向上させます。カウンターの値が変更されても、handleButtonClick関数は再生成されません。

このように、useCallbackフックを使用することで、コールバック関数の再生成を制御し、不要な再レンダリングを避けることができます。メモ化によってパフォーマンスが向上し、不要な関数の生成を減らすことができます。

useRef()

useRefフックは、Reactコンポーネント内で値を保持するために使用されるものです。値の参照を作成し、コンポーネントのライフサイクルを超えて値を保持することができます。

以下に、単純な例を示します。

import React, { useRef } from 'react';

// コンポーネント
const InputFocus = () => {
  const inputRef = useRef(null);

  const handleButtonClick = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleButtonClick}>Focus Input</button>
    </div>
  );
};

export default InputFocus;

上記の例では、InputFocusコンポーネント内にテキスト入力フィールドとボタンがあります。

useRefフックを使用して、inputRefという参照を作成します。

useRef(null)のように初期値を指定することができます。ここでは、テキスト入力フィールドの参照を保持するために使用します。

handleButtonClick関数内で、inputRef.current.focus()を呼び出すことで、テキスト入力フィールドにフォーカスを当てることができます。

このように、useRefフックを使用することで、DOM要素やコンポーネントへの参照を作成し、それらの参照を使用して操作を行うことができます。値の永続化やDOM操作に利用することができます。

useImperativeHandle()

useImperativeHandleフックは、Reactコンポーネント内で子コンポーネントに対して外部からのインターフェースを提供するために使用されるものです。子コンポーネントの参照やメソッドを親コンポーネントから操作できるようにします。

以下に、単純な例を示します。

import React, { useRef, useImperativeHandle, forwardRef } from 'react';

// 子コンポーネント
const ChildComponent = forwardRef((props, ref) => {
  const inputRef = useRef(null);

  // useImperativeHandleフックを使用して外部からアクセス可能なメソッドを定義する
  useImperativeHandle(ref, () => ({
    focusInput: () => {
      inputRef.current.focus();
    }
  }));

  return <input ref={inputRef} type="text" />;
});

// 親コンポーネント
const ParentComponent = () => {
  const childRef = useRef(null);

  const handleButtonClick = () => {
    childRef.current.focusInput();
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleButtonClick}>Focus Input</button>
    </div>
  );
};

export default ParentComponent;

上記の例では、ChildComponentという子コンポーネントを作成しています。

useImperativeHandleフックを使用して、子コンポーネントの参照を親コンポーネントから操作できるようにします。focusInputというメソッドを定義し、その中で子コンポーネント内のテキスト入力フィールドにフォーカスを当てる操作を行っています。

ParentComponent内では、childRefという参照を作成し、子コンポーネントにアクセスできるようにします。

handleButtonClick関数では、childRef.current.focusInput()を呼び出すことで、子コンポーネントのフォーカスメソッドを実行しています。

このように、useImperativeHandleフックを使用することで、子コンポーネントに外部からアクセス可能なメソッドを提供することができます。これにより、親コンポーネントから子コンポーネントを制御することができます。

useLayoutEffect()

useLayoutEffectフックは、ReactコンポーネントがDOMへの変更を反映する直前に同期的に実行されるものです。

useEffectと似ていますが、useLayoutEffectはレンダリング後のすぐに実行されるため、DOMの変更が反映される前に処理を行うことができます。

以下に、単純な例を示します。

import React, { useLayoutEffect, useState } from 'react';

// コンポーネント
const ResizeLogger = () => {
  const [width, setWidth] = useState(window.innerWidth);

  const handleResize = () => {
    setWidth(window.innerWidth);
  };

  // useLayoutEffectフックを使ってウィンドウのリサイズイベントを監視する
  useLayoutEffect(() => {
    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return <p>Window width: {width}px</p>;
};

export default ResizeLogger;

上記の例では、ResizeLoggerコンポーネントがウィンドウの幅を表示します。

useLayoutEffectフックを使用して、ウィンドウのリサイズイベントを監視します。コンポーネントがマウントされた後に実行され、ウィンドウのリサイズイベントを追跡するコールバック関数が登録されます。

また、クリーンアップ関数を返して、コンポーネントがアンマウントされる際にイベントリスナーが解除されるようにしています。

このように、useLayoutEffectフックを使用することで、レンダリング後に同期的に処理を行うことができます。DOMの変更が反映される直前に特定の処理を行いたい場合に有用です。ただし、使用する際は注意が必要であり、パフォーマンスの問題やブラウザのブロッキングについて考慮する必要があります。

useDebugValue()

useDebugValueフックは、Reactデバッグツールにカスタムの表示値を提供するために使用されるものです。デバッグ中に独自のデータや状態を理解しやすくするために利用されます。

以下に、単純な例を示します。

import React, { useState, useDebugValue } from 'react';

// コンポーネント
const Counter = () => {
  const [count, setCount] = useState(0);

  // useDebugValueフックを使ってカウントの値をデバッグツールに表示する
  useDebugValue(count > 5 ? 'High Count' : 'Low Count');

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default Counter;

上記の例では、Counterコンポーネントがカウンターの値を表示し、ボタンをクリックするとカウントが増えます。

useDebugValueフックを使用して、countの値に基づいてデバッグツールにカスタムの表示値を提供します。

ここでは、countの値が5より大きい場合は「High Count」、そうでない場合は「Low Count」という表示値がデバッグツールに表示されます。

これにより、デバッグ中にカウンターの状態がわかりやすくなり、特定の条件に基づいて表示値をカスタマイズできます。

useDebugValueフックは、開発者ツールやデバッグ用のカスタムフック内で特に役立ちます。デバッグや開発時に状態や値をより詳細に表示することができます。

最後に

Reactのフックは、関数コンポーネント内で状態管理や副作用の処理を行うための便利な機能です。これらのフックを使用することで、よりシンプルで効率的なコードを記述することができます。

React開発において非常に強力で重要なツールであり、効率的でメンテナンスしやすいコードを作成するのに役立ちます。

適切に使用することで、よりスケーラブルなアプリケーションを構築することができます。

本日は以上となります。

最後まで読んで頂きありがとうございます。

この記事が役に立ったら、ブックマークと共有をしていただけると幸いです。

プライバシーポリシー

© 2023 Icons8 LLC. All rights reserved.

© [deve.K], 2023. React logo is a trademark of Facebook, Inc. JavaScript is a trademark of Oracle Corporation and/or its affiliates. jQuery and the jQuery logo are trademarks of the JS Foundation. TypeScript and the TypeScript logo are trademarks of the Microsoft Corporation. Next.js and the Next.js logo are trademarks of Vercel, Inc. Firebase and the Firebase logo are trademarks of Google LLC. All logos edited by [deve.K].