🪝

ReactHooks入門!-useStateとuseEffect-

2024/12/14に公開

こんにちは!今回は、React人気の影の立役者ともいえるHooksについて解説します。シンプルで直感的な使い方が、React開発者の生産性を大きく向上させた理由を一緒に見ていきましょう!

Hooksって何?

Hooksは、React 16.8で導入された機能で、関数コンポーネントで状態管理やライフサイクルの制御などができるようになる便利な機能です。

簡単に言うと

  • 「値を保存して、変更できるようにしたい」→useState
  • 「コンポーンネントの表示後に何かしたい」→useEffect

という感じの使い方ができます。

1.useStateで値を管理する

まずは一番基本的なuseStateの例を挙げます。

基本的な使い方

jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  // count: 現在の値
  // setCount: 値を更新する関数
  // useState(0): 初期値を0に設定

  return (
    <div>
      <p>現在のカウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        プラス
      </button>
    </div>
  );
}

このコードでは

  1. countという値を管理します
  2. ボタンをクリックするとsetCountで値が更新されます
  3. 値が更新されると、Reactは仮想DOMを使って変更点を検出し、必要な部分だけを再描画します

複数の値を管理する

jsx
function UserForm() {
  const [name, setName] = useState('');
  const [age, setAge] = useState(0);

  return (
    <div>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="名前を入力"
      />
      <input
        type="number"
        value={age}
        onChange={(e) => setAge(Number(e.target.value))}
        placeholder="年齢を入力"
      />
      <p>名前: {name}</p>
      <p>年齢: {age}</p>
    </div>
  );
}

このように、複数のuseStateを使って、それぞれの値を個別に管理できます。

2.useEffectでタイミングを制御する

次に、useEffectの例を挙げます。これは「いつ」何かを実行するかを制御するためのHooksです。

基本的な使い方

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

function Timer() {
 const [seconds, setSeconds] = useState(0);

 useEffect(() => {
   // コンポーネントが表示されたときに実行される
   console.log('タイマーを開始します');
   
   const interval = setInterval(() => {
     setSeconds(prev => prev + 1);
   }, 1000);

   // クリーンアップ関数(コンポーネントが消えるときに実行される)
   return () => {
     console.log('タイマーを停止します');
     clearInterval(interval);
   };
 }, []); // 空の配列を渡すと、マウント時にだけ実行される

 return <div>{seconds}秒経過</div>;
}

useEffectの使い分け

useEffectは依存配列(第2引数の配列)によって、実行されるタイミングが変わります

jsx
// 1. 毎回の再描画で実行
useEffect(() => {
 console.log('毎回実行されます');//補足⇒コンポーネントが再レンダリングされるたびに実行される
});

// 2. マウント時のみ実行
useEffect(() => {
 console.log('初回のみ実行されます');
}, []);

// 3. 特定の値が変更されたときに実行
useEffect(() => {
 console.log('countが変更されたときに実行されます');
}, [count]);

実践的な例

これらを組み合わせた実践的な例を挙げます!

jsx
function UserProfile() {
 const [userId, setUserId] = useState(1);
 const [userData, setUserData] = useState(null);
 const [loading, setLoading] = useState(false);

 useEffect(() => {
   async function fetchUser() {
     setLoading(true);
     try {
       const response = await fetch(
         `https://api.example.com/users/${userId}`
       );
       const data = await response.json();
       setUserData(data);
     } catch (error) {
       console.error('エラーが発生しました:', error);
     } finally {
       setLoading(false);
     }
   }

   fetchUser();
 }, [userId]); // userIdが変更されたときにデータを再取得

 if (loading) return <div>読み込み中...</div>;
 if (!userData) return <div>ユーザーが見つかりません</div>;

 return (
   <div>
     <h1>{userData.name}さんのプロフィール</h1>
     <p>メール: {userData.email}</p>
     <button onClick={() => setUserId(userId + 1)}>
       次のユーザー
     </button>
   </div>
 );
}

よくある間違い

1.無限ループの発生

jsx
// ⚠️ 良くない例
useEffect(() => {
  setCount(count + 1);  // ⚠️ 依存配列を指定しないと毎回実行され、無限ループになる
});

// ✅ 正しい例
useEffect(() => {
  setCount(count + 1);
}, []); // 依存配列を指定する

2.古い値の参照

jsx
// ⚠️ 良くない例
useEffect(() => {
  const timer = setInterval(() => {
    setCount(count + 1); // 古い値を参照してしまう
  }, 1000);
  return () => clearInterval(timer);
}, []);

// ✅ 正しい例
useEffect(() => {
  const timer = setInterval(() => {
    setCount(prev => prev + 1); // 関数形式で最新の値を参照、(prevは更新前の最新の値)
  }, 1000);
  return () => clearInterval(timer);
}, []);

まとめ

Hooksの基本的な使い方をまとめると

useState

  • 値を保存、更新するために使用
  • 更新すると自動で再描画される
  • 複数の値を個別に管理できる

useEffect

  • 副作用(APIの呼び出しなど)の制御に使用
  • 依存配列で実行タイミングを制御できる
  • クリーンアップ関数でリソースの解放ができる

ご清覧ありがとうございました!!!

Discussion