Welcome to Tech Athletes | テック・アスリート   Click to listen highlighted text! Welcome to Tech Athletes | テック・アスリート

【2026年最新版】React Hooks完全ガイド|useState・useEffect・useContext・カスタムHooksまで実践コードで解説

React Hooksとは?関数コンポーネントで状態管理を実現する仕組み

React Hooksは2019年のReact 16.8でリリースされた機能で、関数コンポーネントでもクラスコンポーネントと同等の機能(状態管理・ライフサイクル等)を使えるようにする仕組みです。現在ではHooksを使った関数コンポーネントがReact開発の標準となっています。

useState:状態管理の基本

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState({ name: "", age: 0 });

  const increment = () => setCount(prev => prev + 1);
  const updateName = (name) => setUser(prev => ({ ...prev, name }));

  return (
    

Count: {count}

updateName(e.target.value)} />
); }

useEffect:副作用の管理

import { useState, useEffect } from "react";

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let isMounted = true;
    setLoading(true);
    
    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => {
        if (isMounted) {
          setUser(data);
          setLoading(false);
        }
      });

    // クリーンアップ関数(アンマウント時に実行)
    return () => { isMounted = false; };
  }, [userId]);  // userId が変化したら再実行

  if (loading) return 
Loading...
; return
{user?.name}
; }

useContext:グローバルな状態共有

import { createContext, useContext, useState } from "react";

// テーマコンテキストの作成
const ThemeContext = createContext(null);

// プロバイダーコンポーネント
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState("light");
  
  const toggleTheme = () =>
    setTheme(prev => prev === "light" ? "dark" : "light");

  return (
    
      {children}
    
  );
}

// コンシューマーコンポーネント
function ThemedButton() {
  const { theme, toggleTheme } = useContext(ThemeContext);
  
  return (
    
  );
}

useMemo・useCallback:パフォーマンス最適化

import { useMemo, useCallback, memo } from "react";

// useMemo: 重い計算結果をメモ化
function ExpensiveComponent({ items, filter }) {
  // filterが変化した時だけ再計算
  const filteredItems = useMemo(() =>
    items.filter(item => item.category === filter),
    [items, filter]
  );

  // useCallback: コールバック関数をメモ化
  const handleClick = useCallback((id) => {
    console.log("Clicked:", id);
  }, []);

  return (
    
    {filteredItems.map(item => ( ))}
); } // memo: コンポーネントをメモ化(propsが変わらなければ再レンダリングしない) const ListItem = memo(({ item, onClick }) => (
  • onClick(item.id)}>{item.name}
  • ));

    useReducer:複雑な状態管理

    import { useReducer } from "react";
    
    const initialState = {
      count: 0,
      loading: false,
      error: null
    };
    
    function reducer(state, action) {
      switch (action.type) {
        case "INCREMENT":
          return { ...state, count: state.count + 1 };
        case "DECREMENT":
          return { ...state, count: state.count - 1 };
        case "RESET":
          return initialState;
        case "SET_LOADING":
          return { ...state, loading: action.payload };
        case "SET_ERROR":
          return { ...state, error: action.payload, loading: false };
        default:
          return state;
      }
    }
    
    function Counter() {
      const [state, dispatch] = useReducer(reducer, initialState);
    
      return (
        

    Count: {state.count}

    ); }

    カスタムHooks:ロジックの再利用

    // useLocalStorage: ローカルストレージとの同期
    import { useState, useEffect } from "react";
    
    function useLocalStorage(key, initialValue) {
      const [storedValue, setStoredValue] = useState(() => {
        try {
          const item = window.localStorage.getItem(key);
          return item ? JSON.parse(item) : initialValue;
        } catch {
          return initialValue;
        }
      });
    
      const setValue = (value) => {
        try {
          const valueToStore = value instanceof Function ? value(storedValue) : value;
          setStoredValue(valueToStore);
          window.localStorage.setItem(key, JSON.stringify(valueToStore));
        } catch (error) {
          console.error(error);
        }
      };
    
      return [storedValue, setValue];
    }
    
    // useDebounce: 入力値のデバウンス
    function useDebounce(value, delay) {
      const [debouncedValue, setDebouncedValue] = useState(value);
    
      useEffect(() => {
        const timer = setTimeout(() => setDebouncedValue(value), delay);
        return () => clearTimeout(timer);
      }, [value, delay]);
    
      return debouncedValue;
    }
    
    // 使用例
    function SearchBox() {
      const [query, setQuery] = useState("");
      const debouncedQuery = useDebounce(query, 300);
    
      useEffect(() => {
        if (debouncedQuery) {
          // 300ms入力が止まったらAPIを叩く
          fetchSearchResults(debouncedQuery);
        }
      }, [debouncedQuery]);
    
      return  setQuery(e.target.value)} />;
    }

    まとめ

    React Hooksを使いこなすことでコードが大幅にシンプルになり、ロジックの再利用性も向上します。useState・useEffect・useContextの基本から、useMemo・useCallbackによるパフォーマンス最適化、カスタムHooksによる抽象化まで段階的に習得していきましょう。

    投稿者 kasata

    IT企業でエンジニアとして勤務後、テクノロジー情報メディア「Tech Athletes(テック・アスリート)」を運営。プログラミング、クラウドインフラ(AWS/GCP/Azure)、AI活用、Webサービス開発を専門とする。エンジニア・ビジネスパーソン向けに、実際に使ってみた経験をもとに信頼できる技術情報を発信中。資格:AWS認定ソリューションアーキテクト、Python 3 エンジニア認定試験合格。

    コメントを残す

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です

    Click to listen highlighted text!