【React.js】React hookを理解する! ~ useReducer編 ~

目次

React hookとは..?

React hookはReact16.8から追加された機能で、クラスコンポーネントでしか使用できなかったstateなどのReactの機能を関数コンポーネントで使用できる機能です。

公式ページは以下です。

この記事ではReact hookのAPIの1つであるuseReducerについて紹介していこうと思います。

公式ページは以下です。

useReducerとは…?

useReducer()useState()の代替であり、(state, action) => newStateという形のreducerを受け取り、現在のstatedispatchとセットで返します。

上記はReduxの知識があれば理解しやすいものかと思います。

Reduxは以下の記事がわかりやすいかと思います。

useState()useReducer()のどちらを使えばいいか迷うかと思います。

useReducer()を使う場合は、複数の値を使用した複雑なstateのロジックがある場合や、前のstateの値に基づいて、次のstateを決定する場合が挙げられます。

また、useReducer()を使用すれば、dispatchを下位コンポーネントに渡せることができるので、深い階層によるstateの更新でもパフォーマンスが落ちにくいようです。

使い方

  • useReducer()reducer関数とstateの初期値を渡します。
  • 戻り値は、statedispatchになります。
const [state, dispatch] = useReducer(reducer関数, stateの初期値);

dispatchとは…?

dispatchとは、引数にactionという、コンポーネントによって実行された操作を受け取ります。

主に{type: 捜査の種類, payload: 操作によって取得、また更新されるデータ}のように、typeプロパティ(actionの識別子)とpayloadプロパティ(データ)で構成されることが多い。

reducer関数とは…?

reducer関数は、stateactionを引数に受け取り、stateを更新する関数のことです。

action.typeをみて、そのtypeに応じたstateの更新処理を記述します。

実際にコードで書いてみました。

例として、数字をカウントするカウンターコンポーネントを作ってみました。

また、API通信を使った場合も実装してみました。

  • useReducer()を用いて数字をカウントする例
import React, { useReducer } from 'react';

const Conter3 = () => {
    // reducerの関数を定義する。
    // stateとactionを引数に渡して、stateを更新する関数。
    const reducerFunction = (state, action) => {
        // actionのタイプによるstateの更新処理を記述する。
        switch (action) {
            case 'increment':
                return state + 1;
            case 'decrement':
                return state - 1;
            case 'reset':
                return 0;
            default:
                return state;
        }
    };

    // useReducerの引数にreducerの関数とステートの初期値を渡す。
    const [counter, dispatch] = useReducer(reducerFunction, 0);
    return (
        <>
            <p>カウント:{counter}</p>
            <button onClick={() => dispatch('increment')}>+1</button>
            <button onClick={() => dispatch('decrement')}>-1</button>
            <button onClick={() => dispatch('reset')}>RESET</button>
            <div className='line'></div>
        </>
    )
}

export default Conter3
import React from 'react';
import { Counter3 } from './components/index';

function App() {
  return (
    <div>
      <p>useReducerのサンプル1です</p>
      <Counter3 />
    </div>
  );
}

export default App;

以下のように動作します。

reducer関数で、actionの値に応じたstateの更新処理を記述しています。

useReducerの引数には、reducer関数とstateの初期値を渡しています。

  • useReducerを用いて数字をカウントする例
import axios from 'axios';
import React, { useReducer } from 'react';

const Address = () => {
    // 初期のステートを定義する。
    const initialState = {
        isLoading: true,
        isError: '',
        data: ''
    }

    // reducerの関数を定義する。
    const reducerFunction = (state, action) => {
        switch (action.type) {
            case 'init':
                return initialState;
            case 'success':
                return {
                    isLoading: false,
                    isError: '',
                    data: action.payload
                };
            case 'fail':
                return {
                    isLoading: false,
                    isError: 'エラーが発生しました。',
                    data: ''
                };
            default:
                return state;
        }
    }

    const [dataState, dispatch] = useReducer(reducerFunction, initialState);

    const fetchData = () => {
        axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';
        axios.defaults.headers.post['Access-Control-Allow-Origin'] = 'http://localhost:3000/';
        // githubのAPIを叩く。
        const url = 'https://api.github.com/users/Tomoki-webpro';
        axios.get(url)
            .then(result => {
                const data = result.data;
                console.log(data)
                dispatch({ type: 'success', payload: data.login });
            })
            .catch(error => {
                dispatch({ type: 'fail' });
            });
    }

    return (
        <>
            <button onClick={fetchData}>githubからデータを取得する</button>
            <p>{ dataState.isLoading ? 'Loading...' : 'Finished!' }</p>
            <p>githubのユーザ名:{dataState.data}</p>
            <p>{ dataState.isError ? dataState.isError : '' }</p>
            <div className='line'></div>
        </>
    )
}

export default Address
import React from 'react';
import { API } from './components/index';

function App() {
  return (
    <div>
      <p>useReducerのサンプル2です</p>
      <API />
    </div>
  );
}

export default App;

以下のように動作します。(成功時)

以下のように動作します。(失敗時)

APIの通信には、axiosを使用しており、githubのAPIを叩いて、自分のgithubのユーザ名を取得しています。

reducerFunctionaction.typeに応じたstateの更新をしています。

dispatchではAPIでデータの取得に成功した場合は、typesuccessにし、payloadに取得したユーザ名を格納しています。

APIでデータの取得に失敗した場合は、typefailに更新しています。

まとめ

今回の記事ではuseReducerを紹介しました。

次回はuseCallbackを紹介しようと思います。

参考記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次