用 Redux-toolkit 串接 React 和 Redux

快還要更快。

簡述

一個 React redux 延伸出來的工具,目的只是要解決原本用 React redux 前置作業太麻煩的問題(像是要建立 store、reducers、actionType 等等)。

如果覺得我寫太爛的話也可以參考這篇,我覺得寫得蠻清楚的。

特色

  • 可以用 mutable 的方式來更新 state(搭配 immer 這個套件達成的)
  • 把需要的東西集中管理(action type、action creator、selector)
  • 方便與其他 middle ware 使用

前置作業

1. 用 create react app

1
npx create-react-app my-app --template redux

2. 現有的 create react app

1
2
3
npm install @reduxjs/toolkit
npm install react-redux
npm install redux

這邊會用第二種方式來一步一步搭建 redux toolkit 環境,這樣比較能知道每個 API 在幹嘛。

這邊也很推薦去看官方文件,內容應該就跟我等一下要講的差不多。

資料夾結構

  • src
    • app
      • store.js
    • features
      • todos
        • todosSlice.js
    • index.js
    • app.js

1. 建立 store

1
2
3
4
5
import { configureStore } from "@reduxjs/toolkit";

export const store = configureStore({
reducer: {},
})

2. 設定 Provider

1
2
3
4
5
6
7
8
9
10
11
12
13
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import { store } from './app/store';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);

這樣子以後就可以使用 redux devtool 了,不用像以前還要加一串。

建立 Slice(最重要的一點)

在 redux toolkit 會用 createSlice 來包含所有東西。簡單來說,一個 Slice 會包含:

  • reducer
  • action creator
  • action type
  • selector

所以依照前面的資料夾結構,會在 /feature/todos/todosSlice.js 建立這樣的內容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
todos: []
}

let id = 0;

// 可以想成是 reducer,但結合了 actionType 跟 action
export const todosSlice = createSlice({
name: 'todos',
initialState,
reducers: {
addTodo: (state, action) => {
state.todos.push({
id: id++,
name: action.payload
});
},
deleteTodo: (state, action) => {
state.todos = state.todos.filter(todo => todo.id !== action.payload);
}
}
})

// 把 action 從 slice 取出
export const { addTodo, deleteTodo } = todosSlice.actions;

// selector
export const selectTodos = state => state.todosReducer.todos;

// 輸出 reducer,注意不用 s
export default todosSlice.reducer

這邊會發現可以用 mutable 的方法來改變 state。再次強調這是因為背後有 immer 幫你做轉換,實際上背後還是 Immutable 的。

接著記得去 store 裡面把 reducer 放進去:

1
2
3
4
5
6
7
8
import { configureStore } from "@reduxjs/toolkit";
import todosReducer from "../features/todos/todosSlice";

export const store = configureStore({
reducer: {
todosReducer
},
})

這樣就完成了。

接著只要用 react-redux 提供的 useSelectoruseDispatch 來結合起來就行了,這邊就不再附了,有任何疑問都可以直接參考我寫的範例

Redux middleware 用 react-redux 把 redux 跟 React 串接起來(Connect 版本)
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×