はじめに
Redux Toolkit の使い方を学んだので、備忘録としてまとめておく。
Redux Toolkit を使った状態管理の基本
基本的な流れは以下の通り。
- スライスの作成
- ストアの作成
- アプリケーションへのストアの提供
- React コンポーネントでの利用
1. スライスの作成
Redux Toolkit では、createSlice
を使えば、State
、Reducer
、Action Creator
をまとめて定義できる。
Immer
というライブラリが使われているため、元の状態を破壊せずに、状態をまるで直接書き換えているような形で記述できる。
import { createSlice } from "@reduxjs/toolkit";
interface UiState {
isModalOpen: boolean;
}
const initialState: UiState = {
isModalOpen: false,
};
export const uiSlice = createSlice({
name: "ui",
initialState,
reducers: {
openModal: (state) => {
state.isModalOpen = true; // Immer により直接変更可能
},
closeModal: (state) => {
state.isModalOpen = false; // Immer により直接変更可能
},
},
});
export const { openModal, closeModal } = uiSlice.actions;
export default uiSlice.reducer;
2. ストアの作成
作成したスライスをストアに登録する。
import { configureStore } from "@reduxjs/toolkit";
import modalReducer from "./modalSlice";
export const store = configureStore({
reducer: {
modal: modalReducer,
},
});
このとき、アプリケーション全体で型安全な状態管理ができるように、ストアから型を抽出しておく。
// ストア内の全 state の型
export type RootState = ReturnType<typeof store.getState>;
// dispatch 関数の型
export type AppDispatch = typeof store.dispatch;
3. アプリケーションへのストアの提供
アプリ全体でストアを使えるように、Provider
でラップする。
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import App from "./App.tsx";
import { store } from "./redux/store.ts";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>
);
4. React コンポーネントでの利用
Redux にアクセスしやすくするため、型情報付きのカスタムフックを定義する。
import { useDispatch, useSelector } from "react-redux";
import { type AppDispatch, type RootState } from "./store";
// ストアから状態を取得するためのフック
export const useAppSelector = useSelector.withTypes<RootState>();
// ストアにアクションをディスパッチするためのフック
export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
使用例:モーダルの開閉
import { useAppDispatch, useAppSelector } from "./redux/hooks";
import { openModal } from "./modalSlice";
function App() {
const isModalOpen = useAppSelector((state) => state.modal.isModalOpen);
const dispatch = useAppDispatch();
const handleOpenModal = () => {
dispatch(openModal());
};
return (
<div>
{isModalOpen && <p>モーダルが開いています。</p>}
<button onClick={handleOpenModal}>モーダルを開く</button>
</div>
);
}
export default App;
感想
- どこからでも状態にアクセスできる便利さに気づいた
- 主にやることは
reducers
の定義で、どんな状態にしたいかを集中して考えればよく、思ったよりシンプルだった