Redux Toolkit 入門:createSliceとconfigureStoreの基本

スポンサーリンク

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 でプロジェクト作成」を参照してください。