Redux middleware

又是 middleware。

簡述

就跟 Express 裡面的 middleware 差不多,Express 的 middleware 是把 request 經過處理後再回傳 response,在 reudx 的 middleware 則是把 action 先經過一段處理後再丟給 reducer 來處理。

簡單來說,原本我們的 action 只能是一個 Object:

1
2
3
4
5
6
7
8
9
10
const ADD_TODO = 'addTodo'

function addTodo(name) {
return {
type: ADD_TODO,
payload: {
name
}
}
}

但加上 middleware 以後,action 變成可以是一個 function

1
2
3
4
5
6
7
function addTodoAsync (name) {
return function (dispatch) {
setTimeout(() => {
dispatch(addTodo(name));
}, 1000)
}
}

這個 function 會被傳入一個 dispatch,你只要把真正要 dispatch 的actionn 寫在裡面就行了。而這也就是 redux-think 這套 middleware 在做的事情

幫你執行 function

就這樣,沒了。

如果還是不太清楚的話,建議參考官方文件的圖,非常一目了然。

範例

這邊沿用 用 Redux-toolkit 串接 React 和 Redux 的範例來做個簡單的示範:

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
34
35
36
37
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
todos: []
}

let id = 0;

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,用非同步的方式來新增 todo
export const addTodoAsync = name => dispatch => {
setTimeout(() => {
dispatch(addTodo(name))
}, 1000)
}


export const { addTodo, deleteTodo } = todosSlice.actions;

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

export default todosSlice.reducer

接著回到 React Component 裡面就能直接使用了:

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
34
35
36
37
38
39
import { selectTodos } from "./features/todos/todosSlice";
import { deleteTodo, addTodoAsync } from './features/todos/todosSlice';
import { useDispatch ,useSelector } from "react-redux";
import { useState } from "react";


function App() {

const [value, setValue] = useState("");
const todos = useSelector(selectTodos);

const dispatch = useDispatch();
const handleSubmit = e => {
e.preventDefault();
if (!value) return;
// 剛剛新增的 action
dispatch(addTodoAsync(value));
setValue("");
}

return (
<div className="App">
<h1>Todos</h1>
<form onSubmit={handleSubmit}>
<input type="text" value={value} onChange={e => setValue(e.target.value)} />
</form>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.name}
<button onClick={() => dispatch(deleteTodo(todo.id))}>delete</button>
</li>
))}
</ul>
</div>
);
}

export default App;

現在就能用非同步的方式來新增 Todo,想看效果的話可以去我寫的範例來試。

mentor-program-day131 用 Redux-toolkit 串接 React 和 Redux
Your browser is out-of-date!

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

×