TK-NOTE

技術的なことや趣味、読んだ本についての感想などを投稿してきます。

useReducerを知る

Cover Image for useReducerを知る
React

useReducer とは何か?

useState と同じで状態を管理するためのReactHooksです。
useReducer の第一引数には reducer 、第二引数には初期値を設定します。
返却値は現在の状態と状態を更新するための dispatch 関数の配列となります。

const [現在の状態, dispatch関数] = useReducer(reducer関数, 初期値);


reducer 関数は第一引数は以前の状態、第二引数にオブジェクトが設定されます。
返却値としては新しい状態を返却します。

const reducer = (元の状態, action) => {
  switch (action.type) {
    case "increment":
      return {
        //新しい状態
      }
    case "decrement":
      return {
        //新しい状態
      }
  }
}


reducerとは状態を更新するための処理のことをいいます。
また、dispatchとはユーザーの操作とReducerのアクションを紐づけるための関数のことをいいます。

useState との違い

基本的に useState で実装できるものは useReducer でも実装できます。
useReducer の特徴としては、状態を更新するための複雑なロジックを実装しやすい点です。
なので、String や Number 型などPrimitiveな情報を管理するときは useState、Objectなど複雑な情報を管理する場合は useReducer を使用したほうが良いと思います。

useReducer を使った実装

useReducer を使ってMovie情報を表示、更新する処理を実装してみました。

import { useReducer } from "react";

function App() {
  const reducer = (prev, action) => {
    switch (action.type) {
      case "UPDATE_TEXT":
        return { ...prev, [action.field]: action.payload };
      case "UPDATE_CHECKBOX":
        const newIsPublished = !prev.isPublished;
        return { ...prev, [action.field]: newIsPublished };
      default:
        throw new Error("unknown type");
    }
  };
  const initialMovieInfo = {
    id: 1,
    title: "test movie title",
    isPublished: false,
  };
  const [movie, dispatch] = useReducer(reducer, initialMovieInfo);

  return (
    <div>
      <h3>id: {movie.id}</h3>
      <h3>title: {movie.title}</h3>
      <h3>isPublished: {movie.isPublished ? "公開" : "非公開"}</h3>
      <div>
        <label htmlFor="title">タイトル</label>
        <input
          id="title"
          type="text"
          value={movie.title}
          onChange={(e) =>
            dispatch({
              type: "UPDATE_TEXT",
              field: "title",
              payload: e.target.value,
            })
          }
        />
      </div>
      <div>
        <label htmlFor="isPublished">公開状態:</label>
        <input
          id="isPublished"
          type="checkbox"
          checked={movie.isPublished}
          onChange={() =>
            dispatch({
              type: "UPDATE_CHECKBOX",
              field: "isPublished",
            })
          }
        />
      </div>
    </div>
  );
}

export default App;