React useReducerフックとは 使い方
本日はReact.jsのuseReducer
フックを初心者様向けに解説していきます。
useReducerはフックの中でも、非常に高度なフックの1つとなっています。
React初心者に関しては実際に使用方法をよく知らない場合がほとんどです。
ですが、このフックはより適切で明確なコードを作成するのに非常に皆様の役に立ってくれるはずです。
是非、覚えて今回でuseStateの勉強から1ランク上へいきましょう。
useStateフックに関する学習は下記になります。
useReducerとは
状態管理フックとしてuseStateこれは、コンポーネントの状態を管理できるようにするフックです。
ただし、useReducer
フックの動作方法はuseStateとはかなり異なります。
代替え品というものです。
これはReact Docs(ドキュメント)もuseReducerフックがuseStateフックの代替えであると示唆しています。
では、どう言った場合に活用するのか?
useReducer
はコンポーネントの階層が深く、複雑な状態を持ち、多くの異なる状態を管理していかなければならない、または以前の状態を元に新しい状態として作る場面での時に使用されます。
最上位のコンポーネントで参照されている状態が、何百個もあった場合、あなたは簡単にそれらを把握することはできますか?
アプリケーションが複雑になるにつれて、状態ツリーはすぐに手に負えなくなる可能性があります。
そのような、複雑さに対処するために提供された最良のパターンの1つがレデューサーとなります。
最上位コンポーネントから任意のコンポーネントに渡すことができます。
これを最上位コンポーネントで定義し、状態をグローバルにすることができます。
そして、すべての状態を管理し1つのオブジェクトによってまとめることができます。
状態を1つのオブジェクトとしてまとめる?
Reduxですか?
気付いた方はいらっしゃるかと思います。
はい、つまり特定のactionがディスパッチされたときにコンポーネントの状態の一部を更新できます。
これは、Reduxの動作と非常によく似ております。
ですが、useReducerの状態は常にオブジェクトである必要はなく制限はありません。
配列
や数値
でも構いません。
useReducerのレデューサーはReduxからのものであり
ReduxはJavaScriptのArray.reduce()
から借用しているのです。
ですので、JavaScriptのMDNでreduce()
について最初から参照されているチュートリアルに戻って学習してみて下さい。
あなたの手助けとなる可能性がございます。
これまでの開発者の間で最も人気のあるフックの1つはこのuseReducer
フックとも言えます。
比較
const [state, setState] = useState(value); const [state, dispatch] = useReducer(reducer, 0);
上記の通り、どちらもこのフックは2つの要素を持つ配列を返します。
useReducerの引数はレデューサー関数と2つの引数を使用してフックを呼び出し、2つ目が初期状態となります。
useReducerフックでは状態
とdispatch
と呼ばれる新しい特別な関数を返すフックという事になります。
ほぼuseStateに近いです。
しかし、レデューサーは3番目の引数もあると言う事も知っておいて下さい。
const [state, dispatch] = useReducer(reducer, 0, init);
上記では3番目の引数があります。
これは、初期状態を遅延的に作成するオプションの値となります。
外部の関数を使用して初期状態の値を計算できます。
useReducerフックは基本的に、関数コンポーネントがアプリケーションの状態管理からレデューサー機能にアクセスできるようにします。
それでは、機能の扱い方を見ていきましょう。
よくある、カウンターコンポーネントでの簡単な例での解説になります。
useReducerフック
まずは全体コードをどうぞ
import { useReducer } from 'react'; const App = () => { const [count, dispatch] = useReducer(myReducer, 0); const myReducer = (state, action) => { switch(action) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: throw new Error() } } return( <div > <header className='App-header'> <p>Counter: {count}</p> <button onClick={() => dispatch('INCREMENT')}>+</button> <button onClick={() => dispatch('DECREMENT')}>-</button> </header> </div> ) } export default App;
DEMO
上記は、初期状態である( 0 )
の値を使用して新しい値を計算する方法を示しております。
では分割しながら解説致します。
App.js/useReducer import { useReducer } from 'react';
しっかり読み込まれるように、インポートをしましょう。
基本的に、レデューサーは状態の変更を管理する機能にすぎません。
ですのでuseStateを理解してれば、レデューサーはそこまで難しいフックではありません。
レデューサーは状態
とaction
2つの引数を取るので現在の状態の値は( 0 )
となります。
const [count, dispatch] = useReducer(myReducer, 0); const myReducer = (state, action) => { switch(action) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: throw new Error() } }
useReducerはSwitch文
を使用される事が多いです。
dispatch
を呼び出すときに指定される引数は、下記ではmyReducer
関数の( action )
に指定されている2番目の引数となります。
const App = () => { const [count, dispatch] = useReducer(myReducer, 0); const myReducer = (state, action) => { switch(action) {} } }
dispatch
関数を使用して、現在の状態を暗黙的に変更するactionをレデューサーに送信可能です。
<button onClick={() => dispatch('INCREMENT')}>+</button> <button onClick={() => dispatch('DECREMENT')}>-</button>
レデューサーは状態とactionを実行する関数であるので任意での値にすることが可能となります。
上記では文字列となっており、DECREMENT
でカウンターを1ずつ減らしていきます。
INCREMENT
は増加なので数が増えていきます。
actionがどのcaseにもマッチしない場合に備えて、必ずデフォルトの状態を返すようにしましょう。
そして、レデューサーはactionを実行した後に新しい状態を返します。
それは、以前の状態を元に新しい状態として作っているという事です。
return( <div > <header className='App-header'> <p>Counter: {count}</p> <button onClick={() => dispatch('INCREMENT')}>+</button> <button onClick={() => dispatch('DECREMENT')}>-</button> </header> </div> )
dispatch
の唯一の仕事はactionを実行し、それらをレデューサーに送信することです。
状態に応じて、レデューサー関数に対して正しいactionがdispatch
されます。
その後、Reactコンポーネントが再度レンダリングされますが、useReducerフックからの新しい状態が使用される事になります。
Reduxは必要ないのか?
useReducerフックの導入によって、Reduxのような外部ライブラリを導入することなく、相当な量の複雑な状態を管理できるようになったのは事実です。
すべてのuseReducer状態を取得し、トップレベルのコンポーネントに配置した場合、Reduxはもう必要ないように感じるかもしれません。
ですが、これはReduxが役に立たないという意味ではありません、Reduxには検討するべき価値のある他の機能や利点がまだたくさんございます。
useReducerがReduxの動作と非常に似ているように見えても、それでもReduxではありません。
このuseReducerフックは、より複雑なアプリケーションではReduxやMobXに置き換わるものではございません。
ですが、単純なアプリケーションではuseReducerフックがReduxを置き換えることができると思います。
Reduxは、グローバルな状態を必要とする大きくて複雑なアプリケーションで作業する必要がある場合、ほとんどのReact開発者にとって頼りになります。
より複雑なアプリの場合は、Reduxのような状態管理ライブラリが引き続き必要になる事は間違いありません。
最後に
レデューサーで従うべき重要なルールの1つは、関数に渡される引数は変更されないままである必要性があります。
同じ引数が渡された場合、関数は常に同じ出力を返します。
そして、レデューサー関数は副作用を引き起こしません。
あなたが、useReducerフックを早く理解したいのであればdispatch
を先に理解すれば、自ずと分かってきます。
useReducerはuseStateとほぼ変わりませんが、ですがむやみやたらと使用するのは避けましょう。
使い分けて、なるべくuseStateを使用していき問題が起きた時はuseReducerで代替えして下さい。
useReducerフックは、React.js用のReduxを必要としない小規模および中規模のアプリケーションに最適となります。
そしてuseReducerを理解できれば、Reduxの学習時の理解も簡単となる事でしょう。
本日は以上となります。
最後まで読んで頂きありがとうございます。
この記事が気に入ったら、ブックマークし他の方に共有してください。