Reactフックを使って、状態管理、データ取得、グローバルなデータ共有を簡単に実現!
初心者向けにuseState、useEffect、useContextを解説します。
Reactは、効率的にUIを作成するためのJavaScriptライブラリです。その中でも「フック(Hooks)」は非常に重要な役割を果たしています。Reactフックを使えば、状態管理やデータの取得、そしてグローバルな状態の共有が簡単に行えるようになります。
1【useState】
useStateは、Reactでコンポーネントに「状態」を持たせるためのフックです。例えば、ボタンをクリックしてカウンターの数値を増やす場合や、フォームの入力値を保持する場合に便利です。
以下に簡単なカウンターコンポーネントを紹介します。
// Counter.jsx
import React, { useState } from "react";
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div style={{ textAlign: "center", marginTop: "20px" }}>
      <h2>useStateでカウントアップ</h2>
      <p style={{ fontSize: "24px" }}>カウント: {count}</p>
      <button
        onClick={() => setCount(count + 1)}
        style={{
          padding: "10px 20px",
          fontSize: "16px",
          backgroundColor: "#007BFF",
          color: "white",
          border: "none",
          borderRadius: "5px",
          cursor: "pointer",
        }}
      >
        カウントアップ
      </button>
    </div>
  );
}
export default Counter;
- useState(0)
- useStateに渡した値(ここでは- 0)が初期値になります。この例では、初期の- countの値は0です。
 
- 更新関数 setCount
- setCountは- countの値を変更するために使います。
- 例えば、setCount(count + 1)を呼ぶと、countが1増加します。
 
- イベントハンドラ
- ボタンのonClickイベントでsetCountを呼ぶことで、ユーザーがボタンをクリックするたびにカウントが1増えるようにしています。
 
- ボタンの
これで「カウントアップ」の機能が完成しました。useStateを使うと、リアルタイムで画面に変化を反映するインタラクティブな要素を簡単に作れることがわかりますね。
2【useEffect】
useEffectは、データの取得、タイマーのセット、イベントリスナーの追加といった「副作用」を管理するためのフックです。初回表示時や、指定したデータが変わるたびに実行する処理を制御できます。
以下に簡単なタイマーコンポーネントを紹介します。
// Timer.jsx
import React, { useState, useEffect } from "react";
function Timer() {
  const [seconds, setSeconds] = useState(0);
  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds((prev) => prev + 1);
    }, 1000);
    return () => clearInterval(interval); // クリーンアップ
  }, []); // 初回マウント時のみ実行
  return (
    <div style={{ textAlign: "center", marginTop: "20px" }}>
      <h2>useEffectでタイマー</h2>
      <p style={{ fontSize: "24px" }}>経過時間: {seconds}秒</p>
    </div>
  );
}
export default Timer;
- useEffect(() => {…}, [])
- useEffectの第一引数には実行したい関数を、第二引数には「依存配列」を渡します。
- ここでは空の配列[]を指定しているため、初回レンダリング時に一度だけ実行され、intervalが設定されます。
 
- 依存配列
- 依存配列に値を指定すると、その値が変わるたびにuseEffect内の処理が再実行されます。
 
- 依存配列に値を指定すると、その値が変わるたびに
- クリーンアップ関数
- returnで関数を返すことで、コンポーネントが削除(アンマウント)された時に- clearIntervalが実行され、タイマーを解除します。
 
この例では、タイマーが1秒ごとにカウントを増やし、コンポーネントが削除されるときにタイマーが解除されています。
3【useContext】
useContextを使うと、アプリ全体で共通の情報を簡単に参照できます。例えば、テーマ(ダークモードやライトモード)やログイン情報をアプリのどのコンポーネントでも利用したい場合に使用できます。
以下に、テーマを各コンポーネント
//ThemeContext.jsx
import React, { createContext } from "react";
export const ThemeContext = createContext();
export function ThemeProvider({ children }) {
  const theme = "dark"; // グローバルテーマを指定
  return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
}
//App.jsx
import React, { useContext } from "react";
import { ThemeProvider, ThemeContext } from "./ThemeContext";
function ThemedComponent() {
  const theme = useContext(ThemeContext);
  const styles =
    theme === "dark"
      ? { backgroundColor: "#333", color: "white", padding: "20px" }
      : { backgroundColor: "white", color: "#333", padding: "20px" };
  return (
    <div style={styles}>
      <h2>useContextでテーマを適用</h2>
      <p>現在のテーマ: {theme}</p>
    </div>
  );
}
function App() {
  return (
    <ThemeProvider>
      <ThemedComponent />
    </ThemeProvider>
  );
}
export default App;
- createContextでコンテキストを作成
- ThemeContextというコンテキストを作成しました。このコンテキストは- "light"(ライトテーマ)をデフォルト値としています。
 
- Providerでコンテキストの値を提供
- ThemeContext.Providerの- value属性に設定した値が、- useContextで取得できるようになります。ここでは- "dark"が提供されています。
 
- useContextで値を取得
- ThemedComponent内で- useContext(ThemeContext)を使うと、- ThemeContextに設定された値(ここでは- "dark")を直接取得できます。
 
この例では、App内の全ての子コンポーネントが、ThemeContextを通じてテーマの値を取得できるようになり、簡単にテーマの切り替えが可能になります。つまりReactの特徴の一つでもあるpropsを使用したデータの受け渡しを使用することなくコンポーネント間でデータの受け渡しができるということですね。深い階層のコンポーネントにデータを渡す時に便利です。
まとめ
- useState: 個別コンポーネントの状態を管理。カウンターのようなシンプルなアプリに最適。
- useEffect: データ取得やタイマーの管理。副作用処理を簡潔に記述可能。
- useContext: グローバルな状態の共有と管理に便利。
これらのフックを活用することで、状態管理やデータの取得がよりスムーズに行えます。
他にも、さまざまなフックが存在するので気になる方は、以下のサイトを見てみるのも面白いかもしれません。
 
                        

