Redux Toolkit 入門:createSliceとconfigureStoreの基本
Redux Toolkitとは
Redux Toolkit(RTK)はReduxの公式ツールキットです。従来のReduxは設定が煩雑でボイラープレートが多かったため、それを解消するために作られました。現在はReduxを使う場合はRTKを使うのが標準です。
インストール
npm install @reduxjs/toolkit react-redux
基本構成
RTKの主要な構成要素は3つです。
| 概念 | 役割 |
|---|---|
createSlice |
状態・reducers・actionsをまとめて定義 |
configureStore |
ストアを作成してsliceを登録 |
useSelector / useDispatch |
コンポーネントからstoreを操作 |
1. Sliceを作成する
// src/store/counterSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
type CounterState = {
count: number
}
const initialState: CounterState = { count: 0 }
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment(state) {
state.count += 1
},
decrement(state) {
state.count -= 1
},
addBy(state, action: PayloadAction<number>) {
state.count += action.payload
},
},
})
export const { increment, decrement, addBy } = counterSlice.actions
export default counterSlice.reducer
RTKでは state.count += 1 のような直接変更の書き方ができます(内部でImmerが不変更新に変換します)。
2. Storeを作成する
// src/store/index.ts
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
3. Providerで囲む
// src/main.tsx import { Provider } from 'react-redux' import { store } from './store' createRoot(document.getElementById('root')!).render( <Provider store={store}> <App /> </Provider> )
4. コンポーネントで使う
import { useSelector, useDispatch } from 'react-redux' import { increment, decrement, addBy } from './store/counterSlice' import type { RootState } from './store' function Counter() { const count = useSelector((state: RootState) => state.counter.count) const dispatch = useDispatch() return ( <div> <p>{count}</p> <button onClick={() => dispatch(increment())}>+1</button> <button onClick={() => dispatch(decrement())}>-1</button> <button onClick={() => dispatch(addBy(10))}>+10</button> </div> ) }
非同期処理:createAsyncThunk
APIからデータを取得するような非同期処理は createAsyncThunk を使います。
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
type User = { id: number; name: string }
export const fetchUser = createAsyncThunk('user/fetch', async (id: number) => {
const res = await fetch(`/api/users/${id}`)
return res.json() as Promise<User>
})
const userSlice = createSlice({
name: 'user',
initialState: { data: null as User | null, loading: false, error: '' },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.loading = true
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.loading = false
state.data = action.payload
})
.addCase(fetchUser.rejected, (state) => {
state.loading = false
state.error = 'エラーが発生しました'
})
},
})
useReducerとの使い分け
useReducer |
Redux Toolkit | |
|---|---|---|
| スコープ | コンポーネント内 | アプリ全体 |
| 共有 | useContextと組み合わせる | Provider1つで全体に |
| DevTools | なし | Redux DevTools使用可 |
| 向いている場面 | 局所的な複雑な状態 | グローバルな状態管理 |
useReducer の考え方は「ReactのuseReducer入門」を参照してください。
まとめ
1. createSlice でstateとreducersを定義 2. configureStore でstoreに登録 3. main.tsx の Provider に store を渡す 4. useSelector で状態を読む 5. useDispatch でactionを送る
Reactのプロジェクト作成から始める場合は「React + Vite でプロジェクト作成」を参照してください。