連載目次 : React入門
前回の記事 : useRef / React Hooks
次回の記事 : useContext / React Hooks
今回はReact Hooksで状態管理ができるuseReducer
について解説を行います。
useStateは単一のステートを管理するのに適していましたが、useReducer
は複数のステートを管理するのに適したHooks APIとなります。
基本的な利用方法
useReducer
を利用する場合にはReactのimport時にuseReducer
を読み込む必要があります。
import React, { useReducer } from 'react';
初期ステートを作成しておき、
const initialState = {count: 0};
ステートを操作するためのreducer関数を作成します。
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1}
case 'decrement':
return {count: state.count - 1}
}
}
そしてfunctionコンポーネントのトップレベルの位置でuseReducer
を利用して状態を保持したstate
オブジェクトと状態を変更するためのreducer
関数を作成します。
const [state, dispatch] = useReducer(reducer, initialState)
こうすればstate.count
として現在のカウント数を増加させたり、dispatch({type: 'decrement'})
という命令でカウントを減算させたり、dispatch({type: 'increment'})
でカウントを加算することができます。
まとめると以下のように利用することができます。
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};
}
}
export default function Foo() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
ただ、このような単純な状態管理はuseState
でも可能ですがuseReducer
の利点は、ステートの更新ロジックをコンポーネントに非依存な外部のreducer関数に渡すことができる点です。
ロジックを分離
例えば以下のサンプルは入力されているテキストが0文字の場合もしくは15文字以上の場合はエラーを表示するというサンプルです。
const initialState = {
text:'',
error: 0
}
function reducer(state, action) {
switch (action.type) {
case 'input':
// error = 0:none 1:empty 2:overflow
const error = action.payload.length === 0 ? 1 : action.payload.length > 15 ? 2 : 0
return {
text: action.payload,
error
};
case 'reset':
return initialState;
}
}
function Foo() {
const [state, dispatch] = useReducer(reducer, initialState);
const handleChange = useCallback(e=>{
dispatch({type:'input',payload:e.target.value})
},[])
const handleReset = useCallback(()=>{
dispatch({type:'reset'})
},[])
return (
<>
<input type="text" value={state.text} onChange={handleChange} />
<input type="button" value="reset" onClick={handleReset} />
{state.error === 1 && <p>空欄です</p>}
{state.error === 2 && <p>15文字以上です</p>}
</>
);
}
ロジックがreducer関数に埋め込まれているので、コンポーネントがシンプルになり、testなどの記述が容易になります。
また、依存する変数が少なくなるので、useCallbackやuseMemoによるパフォーマンスチューニングもしやすくなります。
管理する状態が複雑になりそうな場合はuseState
ではなくuserReducer
の利用を検討してみるのも良いでしょう。
さらにuserReducer
はuseContext
と組み合わせてコンポーネント間にまたがるステートを管理することができます。
次回はuseContext
について解説を行います。
連載目次 : React入門
前回の記事 : useRef / React Hooks
次回の記事 : useContext / React Hooks
【告知】弊社のメンバーが執筆した書籍が発売されました!
弊社のメンバーが執筆した『初心者からちゃんとしたプロになる JavaScript基礎入門』が発売されました! JavaScriptの基礎からVue.jsまでをカバーしており、初学者から基本の復習をしたい方におすすめの1冊です。
フロントエンドエンジニア積極採用中
株式会社トゥーアールでは現在フロントエンドエンジニア積極的に採用中です!
興味がある人は採用ページをチェック!!