Reactの状態管理(useState, useReducer, Redux, Jotai, zustand)を一つのプロジェクト内にカウントカップ関数を作成して比較してみた!
1. useState
useStateを使用した状態管理
const [state, setState] = useState(initialState);
state:現在の状態の値
setState:状態を更新するための関数
initialState:状態の初期値
JSX
<button onClick={() => setState(state + 1)}>+</button>
<button onClick={() => setState(state - 1)}>-</button>
2. useReducer
useReducerを使用した状態管理
const [state, dispatch] = useReducer(reducer, initialState);
reducer:状態の更新ロジックを含む関数
initialState:状態の初期値
state:現在の状態の値
dispatch:アクションを発行するための関数
useReducerの使用例
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
<button onClick={() => dispatch({ type: "+", step: 1 })}>+</button>
<button onClick={() => dispatch({ type: "-", step: 1 })}>-</button>
3. Redux
Store: アプリケーションの状態を保持するオブジェクト
Reducer: 状態の変更を担当する純粋関数。アクションを受け取り、新しい状態を返す。
Action: 状態をどのように変更するかを記述するオブジェクト通常、type プロパティを持つ。
Dispatch: アクションを発行する関数。Storeにアクションを送信して状態を更新する
Reducerの定義
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の設定
const rootReducer = combineReducers({
counter: counterReducer,
});
combineReducersを使用して、複数のreducerを組み合わせることができる。
Storeの作成
export const store = configureStore({
reducer: rootReducer,
});
configureStoreはRedux Toolkitを使用してRedux storeを設定する。ここでrootReducerをreducerとして設定している。
Provider コンポーネント
<Provider store={store}>
<App />
</Provider>
ProviderはReact Reduxライブラリに含まれるコンポーネントで、ReactアプリケーションにReduxのstoreを統合するために使用される。
このコンポーネントは、Reduxのstoreをpropsとして受け取り、Reactのコンテキストを使用してそのstoreをアプリケーションのコンポーネントツリー全体に渡す。
状態の取得とアクションのディスパッチ
const reduxState = useSelector((state) => state.counter.counter);
const reduxDispatch = useDispatch();
useSelector フックを使用してRedux Storeから状態を取得する。
useDispatch フックを使用して、アクションをDispatchする関数を取得する。
JSX
<button onClick={() => reduxDispatch(increment())}>+</button>
<button onClick={() => reduxDispatch(decrement())}>-</button>
4. Jotai
Jotaiは、Reactのための状態管理ライブラリであり、原子(atom)を基本単位として使用する。
Jotaiの基本概念
Atom: 状態の最小単位。Atomは値や状態を保持し、このAtomを通じてコンポーネントが状態を読み書きする。
useAtom: Atomの値を読み取り、更新するためのフック。
Reactコンポーネントでの使用
const [jotaiState, setJotaiState] = useAtom(countAtom);
useAtom: フックを使用して countAtom から状態を読み取り、状態を更新する関数を取得する。
jotaiState: 現在のカウンターの値を保持する。
setJotaiState: カウンターの値を更新するための関数。
JSX
<button onClick={() => setJotaiState(jotaiState + 1)}>+</button>
<button onClick={() => setJotaiState(jotaiState - 1)}>-</button>
5. Zustand
Store: Zustandでは、アプリケーションの状態を保持するオブジェクト。
create: Zustandのストアを作成するための関数。この関数は設定オブジェクトを引数に取り、カスタムフックを返す。
Storeの定義
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コンポーネントでの使用
const zustandState = useCounterStore((state) => state.count);
const { increment: zustandIncrement, decrement: zustandDecrement } = useCounterStore();
useCounterStore フックを使用して、ストアからカウンターの現在値 (zustandState) とアクションクリエーター (zustandIncrement,zustandDecrement) を取得する。
JSX
<button onClick={zustandIncrement}>+</button>
<button onClick={zustandDecrement}>-</button>