Redux 是一個狀態管理庫,主要用來管理應用中的全局狀態,特別是當應用變得複雜時。Redux Toolkit(RTK)是官方推薦的開發 Redux 應用的工具集,它大大簡化了 Redux 開發,並幫助減少樣板程式碼的撰寫。
Redux Toolkit 是 Redux 官方提供的一個專門用來簡化 Redux 開發的工具包。它提供了以下核心功能:
在使用 Redux Toolkit 之前,我們需要安裝相應的依賴項目,包括 @reduxjs/toolkit 和 react-redux:
npm install @reduxjs/toolkit react-redux
先簡單回顧 Redux 的核心概念:
Redux store 是整個應用狀態的容器。使用 Redux Toolkit,我們可以輕鬆創建一個 store:
// store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counter/counterSlice';
const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});
export default store;
使用 configureStore() 來創建 Redux store,它接受一個包含所有 reducer 的對象。
並在創建 counterReducer。
Slice 是 Redux Toolkit 的一個新概念,它將 reducer、action 和 state 全部包裝在一起。每個 slice 都代表應用中的一部分狀態。
我們來創建一個簡單的 counter slice,該 slice 包含一些增加和減少計數器的邏輯。
// features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0,
  },
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
我們使用了 createSlice(),這個函數會自動生成 action 和 reducer。increment、decrement 和 incrementByAmount 是我們定義的 action,state.value 是我們要管理的狀態。
現在,我們需要將 Redux store 提供給整個 React 應用。我們使用 Provider 來將 store 傳遞給 React 組件樹。
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
Provider 將 store 連接到 React 應用中的所有組件,這樣每個組件都能夠訪問全局狀態。
接下來,我們來看看如何在組件中訪問 Redux 狀態並派發 action。
Redux Toolkit 提供了兩個重要的 hook:useSelector 和 useDispatch。
useSelector:用於從 Redux store 中選擇狀態。useDispatch:用於派發 action。
// Counter.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './features/counter/counterSlice';
function Counter() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();
  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
      <button onClick={() => dispatch(incrementByAmount(5))}>+5</button>
    </div>
  );
}
export default Counter;
我們使用了 useSelector 來從 store 中選擇計數器的 value,並使用 useDispatch 來派發 increment、decrement 和 incrementByAmount action來更改狀態的值。
看完教學之後,馬來上動手實作看看!今天是要把 Day18 的TodoList小作品做個重構,讓原先用 Redux 的狀態管理改用成Redux ToolKit 吧!同時加深學習印象~那就來實作吧!
npm install @reduxjs/toolkit react-redux
createSlice 定義 Slice在 Redux Toolkit 中,你可以使用 createSlice 來同時定義 reducer 和 action。這樣可以減少樣板程式碼的撰寫。
// reducers/todoSlice.js
import { createSlice } from '@reduxjs/toolkit'
// 定義初始狀態
const initialState = {
  todos: [
    { id: 1, text: '學習 React', completed: false },
    { id: 2, text: '完成作業', completed: false },
  ],
}
// 使用 createSlice 創建 todoSlice
const todoSlice = createSlice({
  name: 'todos',
  initialState,
  reducers: {
    addTodo: (state, action) => {
      state.todos.push({ id: Date.now(), text: action.payload, completed: false })
    },
    toggleComplete: (state, action) => {
      const todo = state.todos.find(todo => todo.id === action.payload)
      if (todo) {
        todo.completed = !todo.completed
      }
    },
    deleteTodo: (state, action) => {
      state.todos = state.todos.filter(todo => todo.id !== action.payload)
    },
  },
})
// 將 action 和 reducer 導出
export const { addTodo, toggleComplete, deleteTodo } = todoSlice.actions
export default todoSlice.reducer
使用 configureStore 來設定 store,這會自動幫你加入 Redux DevTools 及 middleware。
// store.js
import { configureStore } from '@reduxjs/toolkit'
import todoReducer from './reducers/todoSlice'
// 創建 Redux store
const store = configureStore({
  reducer: {
    todos: todoReducer,
  },
})
export default store
將 Redux store 提供給應用的組件:
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import App from './App'
import store from './store'
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)
useSelector 和 useDispatch 在 React 中操作 Redux 狀態可以使用 useSelector 來取得 store 的狀態,使用 useDispatch 來發送 action:
import { useSelector, useDispatch } from "react-redux";
import { addTodo, toggleComplete, deleteTodo } from "./reducers/todoSlice";
  // 使用 useSelector 取得 todos 狀態
  const todos = useSelector((state) => state.todos.todos);
  // 使用 useDispatch 發送 action
  const dispatch = useDispatch();
  // 定義處理函式,使用 Redux Toolkit 的 action creators
  const handleAddTodo = (text) => {
    dispatch(addTodo(text));
  };
  const handleToggleComplete = (id) => {
    dispatch(toggleComplete(id));
  };
  const handleDeleteTodo = (id) => {
    dispatch(deleteTodo(id));
  };
透過使用 Redux Toolkit,我們能夠簡化 Redux 的使用方式:
createSlice 幫助我們同時定義 action 和 reducer,避免撰寫重複的程式碼。configureStore 簡化了 store 的設定。useSelector 和 useDispatch 來操作 store,讓程式碼變得更簡潔可讀。這樣就完成了從傳統 Redux 到 Redux Toolkit 的轉換。
完整程式碼:App.js - nodebox - CodeSandbox
這篇文章介紹了如何使用 Redux Toolkit 來簡化 React 應用中的狀態管理,通過 configureStore、createSlice,我們可以更輕鬆地處理邏輯,並減少樣板程式碼的撰寫。再透過從傳統 Redux 到 Redux Toolkit 的轉換。最後可以試著玩看看 Redux DevTools 工具,並試著用這工具抓Bug吧!