Reactの状態管理の比較(useState, useReducer, Redux, Jotai, Zustand)

Reactの状態管理(useState, useReducer, Redux, Jotai, zustand)を一つのプロジェクト内にカウントカップ関数を作成して比較してみた！

:::note info
[github コード全体](https://github.com/mori-tt/State_Management_Comparison)
:::

## <font color="Blue">1. useState</font>


#### useStateを使用した状態管理
```App.jsx
const [state, setState] = useState(initialState);
```
state:現在の状態の値
setState:状態を更新するための関数
initialState:状態の初期値


#### JSX
```App.jsx
<button onClick={() => setState(state + 1)}>+</button>
<button onClick={() => setState(state - 1)}>-</button>
```



## <font color="Blue">2. useReducer</font>

#### useReducerを使用した状態管理
```App.jsx
const [state, dispatch] = useReducer(reducer, initialState);
```
reducer:状態の更新ロジックを含む関数
initialState:状態の初期値
state:現在の状態の値
dispatch:アクションを発行するための関数

#### useReducerの使用例
```App.jsx
const [rstate, dispatch] = useReducer((state, action) => {
  switch (action.type) {
    case "+":
      return state + action.step;
    case "-":
      return state - action.step;
    default:
      throw new Error("Unknown action");
  }
}, 0);
```
rstate はカウンターの現在値を保持し、初期値は 0 です。dispatch 関数を使ってアクションを発行し、状態を更新します。

#### JSX
```App.jsx
<button onClick={() => dispatch({ type: "+", step: 1 })}>+</button>
<button onClick={() => dispatch({ type: "-", step: 1 })}>-</button>
```

## <font color="Blue">3. Redux</font>
Store: アプリケーションの状態を保持するオブジェクト

Reducer: 状態の変更を担当する純粋関数。アクションを受け取り、新しい状態を返す。

Action: 状態をどのように変更するかを記述するオブジェクト通常、type プロパティを持つ。

Dispatch: アクションを発行する関数。Storeにアクションを送信して状態を更新する

#### Reducerの定義
```App.jsx
const counterReducer = (state = { counter: 0 }, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { ...state, counter: state.counter + 1 };
    case "DECREMENT":
      return { ...state, counter: state.counter - 1 };
    default:
      return state;
  }
};
```
counterReducer はカウンターの値を管理するReducerです。INCREMENT アクションでカウンターを増加させ、DECREMENT アクションで減少させる。

#### Root Reducerの設定
```App.jsx
const rootReducer = combineReducers({
    counter: counterReducer,
});
```
combineReducersを使用して、複数のreducerを組み合わせることができる。

#### Storeの作成
```App.jsx
export const store = configureStore({
    reducer: rootReducer,
});
```
configureStoreはRedux Toolkitを使用してRedux storeを設定する。ここでrootReducerをreducerとして設定している。

#### Provider コンポーネント
```main.jsx
<Provider store={store}>
  <App />
</Provider>
```
ProviderはReact Reduxライブラリに含まれるコンポーネントで、ReactアプリケーションにReduxのstoreを統合するために使用される。
このコンポーネントは、Reduxのstoreをpropsとして受け取り、Reactのコンテキストを使用してそのstoreをアプリケーションのコンポーネントツリー全体に渡す。

#### 状態の取得とアクションのディスパッチ
```App.jsx
const reduxState = useSelector((state) => state.counter.counter);
const reduxDispatch = useDispatch();
```
useSelector フックを使用してRedux Storeから状態を取得する。
useDispatch フックを使用して、アクションをDispatchする関数を取得する。

#### JSX
```App.jsx
<button onClick={() => reduxDispatch(increment())}>+</button>
<button onClick={() => reduxDispatch(decrement())}>-</button>
```

## <font color="Blue">4. Jotai</font>
Jotaiは、Reactのための状態管理ライブラリであり、原子（atom）を基本単位として使用する。
#### Jotaiの基本概念
Atom: 状態の最小単位。Atomは値や状態を保持し、このAtomを通じてコンポーネントが状態を読み書きする。

useAtom: Atomの値を読み取り、更新するためのフック。

#### Reactコンポーネントでの使用
```App.jsx
const [jotaiState, setJotaiState] = useAtom(countAtom);
```
useAtom: フックを使用して countAtom から状態を読み取り、状態を更新する関数を取得する。

jotaiState: 現在のカウンターの値を保持する。

setJotaiState: カウンターの値を更新するための関数。

#### JSX
```App.jsx
<button onClick={() => setJotaiState(jotaiState + 1)}>+</button>
<button onClick={() => setJotaiState(jotaiState - 1)}>-</button>
```


## <font color="Blue">5. Zustand</font>

Store: Zustandでは、アプリケーションの状態を保持するオブジェクト。

create: Zustandのストアを作成するための関数。この関数は設定オブジェクトを引数に取り、カスタムフックを返す。

#### Storeの定義
```App.jsx
const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));
```
ここで定義された useCounterStore は、カウンターの状態と、その状態を変更するための increment と decrement 関数を含むカスタムフック。set 関数は現在の状態を引数に取り、新しい状態を返す関数を受け取る。

#### Reactコンポーネントでの使用
```App.jsx
const zustandState = useCounterStore((state) => state.count);
const { increment: zustandIncrement, decrement: zustandDecrement } = useCounterStore();
```
useCounterStore フックを使用して、ストアからカウンターの現在値 (zustandState) とアクションクリエーター (zustandIncrement,zustandDecrement) を取得する。

#### JSX
```App.jsx
<button onClick={zustandIncrement}>+</button>
<button onClick={zustandDecrement}>-</button>
```