useReducer Hook 介紹
useReducer
Hook 介紹
useReducer
是 React 中的一個 Hook,用來在函數組件中管理更為複雜的狀態邏輯。相比 useState
,useReducer
更適合處理多層次且有邏輯分支的狀態更新,特別是在多個子狀態需要基於不同動作進行更新的情況下。
1. useReducer
的基本概念
useReducer
的工作原理與 Redux 中的 Reducer 相似,它接收一個 reducer 函數和初始狀態,返回當前狀態以及一個 dispatch 函數。當我們調用 dispatch
函數時,會根據指定的 action 來調用 reducer,進而更新狀態。
- Reducer 是一個純函數,它根據當前的狀態和傳入的 action 來決定並返回新的狀態。
- Action 是一個帶有類型(
type
)和可選數據(payload
)的對象,用來描述狀態變更的具體操作。
2. useReducer
的語法
1
const [state, dispatch] = useReducer(reducer, initialState);
state
:當前的狀態值。dispatch
:一個函數,調用時傳入一個 action 對象,觸發 reducer 函數更新狀態。reducer
:一個純函數(state, action) => newState
,負責根據 action 決定如何更新狀態。initialState
:初始狀態。
3. 基本範例
以下是一個使用 useReducer
來實現計數器的範例:
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 React, { useReducer } from 'react';
// 定義 reducer 函數
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
throw new Error();
}
}
function Counter() {
const initialState = { count: 0 };
// 使用 useReducer
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>增加</button>
<button onClick={() => dispatch({ type: 'decrement' })}>減少</button>
<button onClick={() => dispatch({ type: 'reset' })}>重置</button>
</div>
);
}
export default Counter;
解釋:
- 我們創建了一個
reducer
函數,它接收當前狀態state
和action
,根據不同的action.type
返回新的狀態。 - 使用
useReducer
來管理計數器的狀態,初始狀態設為{ count: 0 }
。 - 點擊按鈕時,通過
dispatch
傳遞不同的action
來觸發狀態更新。
4. useReducer
的優勢
- 更好的狀態管理:當狀態變更邏輯複雜時,
useReducer
可以將邏輯集中在一個 reducer 函數中,代碼更清晰、易於維護。 - 避免多次調用
setState
:使用useState
處理多個相關狀態時,會有多次setState
調用,而useReducer
可以將這些邏輯整合為一個狀態更新步驟。 - 提高可測試性:
reducer
函數是一個純函數,更容易進行單元測試,因為它不依賴於外部變量或副作用。
5. 複雜範例:表單數據管理
假設我們有一個包含多個輸入字段的表單,我們可以使用 useReducer
來管理表單的狀態。
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import React, { useReducer } from 'react';
// 定義初始狀態
const initialState = {
username: '',
email: '',
password: ''
};
// 定義 reducer 函數
function reducer(state, action) {
switch (action.type) {
case 'setField':
return {
...state,
[action.field]: action.value
};
case 'reset':
return initialState;
default:
throw new Error();
}
}
function SignupForm() {
const [state, dispatch] = useReducer(reducer, initialState);
const handleChange = (e) => {
dispatch({
type: 'setField',
field: e.target.name,
value: e.target.value
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('提交表單: ', state);
dispatch({ type: 'reset' });
};
return (
<form onSubmit={handleSubmit}>
<label>
使用者名稱:
<input
name="username"
value={state.username}
onChange={handleChange}
/>
</label>
<br />
<label>
電子郵件:
<input name="email" value={state.email} onChange={handleChange} />
</label>
<br />
<label>
密碼:
<input
type="password"
name="password"
value={state.password}
onChange={handleChange}
/>
</label>
<br />
<button type="submit">註冊</button>
</form>
);
}
export default SignupForm;
解釋:
- 我們將表單的每個字段的狀態整合在一個
state
對象中,並使用reducer
函數來處理不同的字段變更。 - 每當用戶輸入數據時,會觸發
dispatch
,根據字段名稱和值更新狀態。 - 提交表單後,表單狀態會重置為初始狀態。
6. useReducer
與 useState
的比較
特點 | useState | useReducer |
---|---|---|
適用場景 | 簡單狀態變更和邏輯 | 複雜狀態邏輯,多個狀態基於不同的操作進行更新 |
狀態更新方式 | 直接調用 setState | 通過 dispatch 發送 action 觸發狀態更新 |
狀態更新邏輯 | 單純更新狀態,使用較少邏輯 | 使用 reducer 將邏輯和狀態更新分離 |
可擴展性 | 對於多狀態較難擴展 | 更易於擴展和管理複雜的多狀態更新 |
- 如果你的狀態變化相對簡單,可以直接使用
useState
。 - 如果你的狀態變化涉及到多個子狀態或者多種操作(例如有不同的行為需要觸發不同的狀態變更),
useReducer
會是一個更合適的選擇。
7. 總結
useReducer
是管理複雜狀態邏輯的一個強大工具,它適合多層次狀態變化或有明確行為類型的應用場景。- 通過
reducer
函數將狀態邏輯與組件分離,提升了代碼的可維護性和可測試性。 useReducer
也能和useContext
結合,來實現全局狀態管理,類似於 Redux 的功能。
在 React 應用中,根據具體的狀態管理需求,可以靈活選擇 useState
或 useReducer
來管理狀態。
本文章以 CC BY 4.0 授權