React hookとは..?
React hookはReact16.8から追加された機能で、クラスコンポーネントでしか使用できなかったstateなどのReactの機能を関数コンポーネントで使用できる機能です。
公式ページは以下です。
この記事ではReact hookのAPIの1つであるuseReducerについて紹介していこうと思います。
公式ページは以下です。
- 【React.js】React hookを理解する! ~ useState編 ~
- 【React.js】React hookを理解する! ~ useEffect編 ~
- 【React.js】React hookを理解する! ~ useContext編 ~
- 【React.js】React hookを理解する! ~ useReducer編 ~ ◀︎◀︎◀︎ 今回のテーマ😃
- 【React.js】React hookを理解する! ~ useCallback編 ~
- 【React.js】React hookを理解する! ~ useMemo編 ~
- 【React.js】React hookを理解する! ~ useRef編 ~
useReducerとは…?
useReducer()はuseState()の代替であり、(state, action) => newStateという形のreducerを受け取り、現在のstateをdispatchとセットで返します。
上記はReduxの知識があれば理解しやすいものかと思います。
Reduxは以下の記事がわかりやすいかと思います。

useState()とuseReducer()のどちらを使えばいいか迷うかと思います。
useReducer()を使う場合は、複数の値を使用した複雑なstateのロジックがある場合や、前のstateの値に基づいて、次のstateを決定する場合が挙げられます。
また、useReducer()を使用すれば、dispatchを下位コンポーネントに渡せることができるので、深い階層によるstateの更新でもパフォーマンスが落ちにくいようです。
使い方
- useReducer()にreducer関数とstateの初期値を渡します。
- 戻り値は、stateとdispatchになります。
const [state, dispatch] = useReducer(reducer関数, stateの初期値);
dispatchとは…?
dispatchとは、引数にactionという、コンポーネントによって実行された操作を受け取ります。
主に{type: 捜査の種類, payload: 操作によって取得、また更新されるデータ}のように、typeプロパティ(actionの識別子)とpayloadプロパティ(データ)で構成されることが多い。
reducer関数とは…?
reducer関数は、stateとactionを引数に受け取り、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のユーザ名を取得しています。
reducerFunctionでaction.typeに応じたstateの更新をしています。
dispatchではAPIでデータの取得に成功した場合は、typeをsuccessにし、payloadに取得したユーザ名を格納しています。
APIでデータの取得に失敗した場合は、typeをfailに更新しています。
まとめ
今回の記事ではuseReducerを紹介しました。
次回はuseCallbackを紹介しようと思います。
参考記事

コメント