1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReactにおけるuseReducerについて

Last updated at Posted at 2024-11-15

useReducerとuseStateの比較

useStateuseReducerは、Reactで状態管理を行うためのフックですが、それぞれ異なる用途と特性があります。

useState

  • 用途: シンプルな状態管理。状態が1つまたは少数の場合に適しています。

  • 構文:

    const [state, setState] = useState(initialState);
    
  • 状態更新:

    • 状態を直接変更するための関数(setState)を使用します。
    • 更新は即時の状態を反映しない場合があるため、前の状態に依存する場合は関数形式で更新する必要があります。
  • :

    const [count, setCount] = useState(0);
    
    const increment = () => setCount(count + 1); // 状態を直接変更
    // もしくは
    const increment = () => setCount(prevCount => prevCount + 1); // 前の状態に依存
    

useReducer

  • 用途: 複雑な状態管理や、状態の変更が多い場合に適しています。特に、状態がオブジェクトであったり、複数の状態が関連している場合に有効です。

  • 構文:

    const [state, dispatch] = useReducer(reducer, initialState);
    
  • 状態更新:

    • 状態更新はアクションをディスパッチすることで行います。アクションにはタイプと必要なデータが含まれます。
    • reducer関数が状態とアクションを受け取り、新しい状態を返します。
  • :

    const initialState = { count: 0 };
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return { count: state.count + 1 };
        case 'decrement':
          return { count: state.count - 1 };
        default:
          throw new Error();
      }
    }
    
    const [state, dispatch] = useReducer(reducer, initialState);
    
    const increment = () => dispatch({ type: 'increment' }); // アクションをディスパッチ
    

useReducerの実装パターン別の実装例

以下に、useReducerを使った異なる実装パターンの雛形を示します。

1. 基本的なカウンター

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

export default function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}

2. 複数の状態を持つ

import React, { useReducer } from 'react';

const initialState = { count: 0, text: '' };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 };
    case 'setText':
      return { ...state, text: action.text };
    default:
      throw new Error();
  }
}

export default function MultiState() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <input
        type="text"
        value={state.text}
        onChange={e => dispatch({ type: 'setText', text: e.target.value })}
      />
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
    </div>
  );
}

3. APIからのデータ取得

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

const initialState = { loading: true, data: null, error: null };

function reducer(state, action) {
  switch (action.type) {
    case 'fetchSuccess':
      return { loading: false, data: action.data, error: null };
    case 'fetchError':
      return { loading: false, data: null, error: action.error };
    default:
      throw new Error();
  }
}

export default function FetchDataComponent() {
  const [state, dispatch] = useReducer(reducer, initialState);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        dispatch({ type: 'fetchSuccess', data });
      } catch (error) {
        dispatch({ type: 'fetchError', error: error.message });
      }
    };

    fetchData();
  }, []);

  if (state.loading) return <p>Loading...</p>;
  if (state.error) return <p>Error: {state.error}</p>;
  
  return (
    <div>
      <h1>Data:</h1>
      <pre>{JSON.stringify(state.data, null, 2)}</pre>
    </div>
  );
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?