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吧!