SAMURAI TERAKOYA

【React hooks】useReducerの基礎を習得 – カウンターアプリ

React.js

※ 本記事は、以下の記事の続きになります。

上記の記事では、useStateとpropsを用いて値の状態を管理しつつ、コンポーネント間の値の受け渡しを実現することでカウンターアプリを作成していきました。
本記事では、useStateを使用せず、usereducerを使用してカウンターアプリのコードを書き換えてみたいと思います。

useReducerとは

React hooksにおいて提供されている関数の1つになり、値の状態の保持・更新などを行う点は、useStateと変わりありません。
となると、useStateでいいじゃないと思うかもしれませんが、次のような状況下でメリットを発揮するので、useSateとの使い分けを行う際に備え、覚えておきましょう。
条件式に応じて、複数の処理に分岐するような処理が行われるようなプログラム更新前の値に基づいて、次の値を操作したい場合など
React_hooks_usereducer_解説
useStateでは、具体的な処理までは関数ごとに処理を記述し、呼び出すことによって値の更新を行ったりします。しかし、useReducerは、dispatchからactionに対して渡された値に応じてuseReducer内の条件式を分岐させ、各々の処理結果を呼び出し元へ返していきます。
つまり、条件式を分岐させるうえで必要なactionの受け渡し以外は、全てuseReducer内で行ってしまうため、この点では、useStateと大きく違ってくることが分かると思います。

カウンターアプリを書き換える

ここまで主にテキストで説明しましたが、テキストのみで理解するのは難しいため、実際にuseStateで作成されているカウンターアプリをuseReducerで書き換えてみましょう。
(※ 修正するのは、App.jsとCounter.cssになります。)

App.jsの書き換え

以下、今回編集する箇所になります。

const [countval, setCountVal] = useState(initialState);

const App = () => {
  // 更新前のcountvalを+1する
  const CounterUp = () => {
    setCountVal(prevcount => prevcount + 1);
  }
  // 更新前のcountvalを-1する  
  const CounterDown = () => {
    setCountVal(prevcount =>  
       prevcount > 0 ? prevcount - 1 : prevcount);
  }
  // 初期値(0)にリセットする
  const CounterReset = () => {
    setCountVal(initialState);
  }

では、早速、進めていきましょう。

カウンターアプリ 修正
  • useReducerを使用するには、importしてあげないといけません。useStateをuseReducerに変更しましょう。

    import { useState } from "react";
    ↓
    import { useReducer } from "react";

  • useReducerを定義

    (prevcount, {value}) => {}, 0)の部分について、少し解説しますと、第一引数のprevcountで更新前の値(countvalが保持している値)を取得し、第二引数の{value}でdispatchから渡されるアクションを受け取れるようにしています。

    {}内では、渡されたアクションを元に条件式を書いていき、0は、カウンターの初期値になります。

    // const [countval, setCountVal] = useState(initialState);
    const [countval, dispatch] = useReducer((prevcount, {value}) => {},0);

  • 関数部分の修正

    続いて、関数部分を修正します。dispatchでアクションに渡していく値を記述していきます。設定する値は、以下のようにします。

    +1 : “add“,  -1 : “minus” ,  リセット : “reset
    const CounterUp = () => { 
      dispatch({value: "add"});
    }
    
    const CounterDown = () => {
      dispatch({value: "minus"});
    }
    
    const CounterReset = () => {
      dispatch({value: "reset"});
    }
    
    
    useReducerを定義する際に設定したアクションは、valueになりますが、{value: 値}という形でdispatch内に記述してあげることで、アクションに値を渡すことが出来ます。
    元々、処理として、書いていたのは何処にいったのか?と疑問に感じる方もいるかと思いますが、それは次で解説していきます。

  • 条件式の記述

    最後になりますが、ここでは各関数から渡されたアクションをuseReducer内の条件式に当てはめていきます。条件式は、switch文もしくはif文で書きますが、どちらでも書きやすいほうでOKです。

    valueで受け取った値を元にcase文で条件を分岐させることで、dispatchから渡された値を元に処理を分けることが出来ます。

    switch(value) { 
      case "add" :
        return prevcount + 1;
      case "minus" :
        return prevcount > 0 ? prevcount - 1 : prevcount;
      case "reset" :
        return initialState;
      default :
        throw new Error("エラー")
      }

    例えば、+ボタンが押下されたときには、CounterUp関数が呼ばれますので、valueで”add”を受け取ります。その際の処理は、return prevcount + 1 になるため、更新前の値に+1された値が結果と返されます。

    また、全てのcase文に一致しない値が渡された場合には、default文内の処理が実行され、エラーを返すような構造にしています。

  • 最終コード確認

    以上でコードの修正自体は終了になります。以下のコードが修正後のコードになりますので、スペルミスが記述する箇所が間違っていないかチェックしましょう。

    import { useReducer } from "react";
    import CounterResult from "./child/CounterResult";
    import "./Counter.css";
    
    const [countval, dispatch] = useReducer((prevcount, {value}) => {
      switch(value) { 
        case "add" :
          return prevcount + 1;
        case "minus" :
          return prevcount > 0 ? prevcount - 1 : prevcount;
        case "reset" :
          return initialState;
        default :
          throw new Error("エラー")
      }
    },0);
    
    const CounterUp = () => { 
      dispatch({value: "add"});
    }
    
    const CounterDown = () => {
      dispatch({value: "minus"});
    }
    
    const CounterReset = () => {
      dispatch({value: "reset"});
    }
    
     return (
       <>
         <div className="main">
         <h1>Counter_App</h1>
           <CounterResult 
               countval={countval} 
               Up={CounterUp} 
               Down={CounterDown}
               Reset={CounterReset} 
           />
        </div>  
       </>
      );
    
    };
    
    export default App;

Counter.cssの修正

修正箇所については、色に関する部分のみになります。(コードは修正箇所のみになりますので、全体的なコードは、https://utubou-tech.com/counter_react_usestate/#toc9 にてご確認ください。)

#root { 
  width: 100%;
  height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgb(255, 254, 240); /* 修正箇所  */
}

.main {
  margin: 0 auto;
  border: 2px dashed rgb(8, 63, 2); /* 修正箇所  */
  padding: 30px;
}

.main h1 {
  color: rgb(151, 252, 114); /* 修正箇所  */
}

動作確認

では、ここまで如何でしたでしょうか?? 以下のコマンドを実行し、最後に動作の確認をしてみましょう。

cd プロジェクトフォルダ
npm start 

正常に実行されますと、以下のように表示されます。しっかりと値も動くか確認しましょう。

まとめ

本記事では、以下の内容を確認していきました。

  • useReducerとuseStateの違い
  • useReducerの使い方
  • useStateで作られているアプリをuseReducerで書き換える方法

次回は、useCountextについてまとめていけたらと思います。

 

コメント

タイトルとURLをコピーしました