useReducer()
是 React Hooks API 中的一個方法,與useState
類似,但為您提供了更多控制權來管理狀態。它接受一個reducer函數和初始狀態作為參數,並傳回狀態和調度方法:
const [state, dispatch] = React.useReducer(reducerFn, initialState, initFn);
reducer(之所以這樣稱呼,是因為您將傳遞給陣列方法Array.prototype.reduce(reducer, initialValue)
函數類型)是取自 Redux 的模式。如果您不熟悉 Redux,簡而言之,reducer 是一個純函數,它將先前的狀態和操作作為參數,並傳回下一個狀態。
(prevState, action) => newState
操作是描述發生的事情的一條訊息,並且根據該訊息,reducer 指定狀態應如何變更。動作透過dispatch(action)
方法傳遞。
大多數時候,您只需使用useState()
方法就可以了,該方法建立在useReducer()
之上。但有些情況下useReducer()
較可取。
當狀態依賴前一個方法時,使用此方法總是更好。它會給你一個更可預測的狀態轉換。簡單的例子是:
function reducer(state, action) {
switch (action.type) {
case 'ADD': return { count: state.count + 1 };
case 'SUB': return { count: state.count - 1 };
default: return state;
}
}
function Counter() {
const [state, dispatch] = React.useReducer(reducer, { count: 0 });
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'ADD'})}>Add</button>
<button onClick={() => dispatch({type: 'SUB'})}>Substract</button>
</>
);
}
當狀態包含多個原始值時,例如巢狀物件或陣列。例如:
const [state, dispatch] = React.useReducer(
fetchUsersReducer,
{
users: [
{ name: 'John', subscribred: false },
{ name: 'Jane', subscribred: true },
],
loading: false,
error: false,
},
);
管理這種本地狀態更容易,因為參數相互依賴,並且所有邏輯都可以封裝到一個reducer中。
reducer是純函數,這意味著它們沒有副作用,並且在給定相同參數的情況下必須返回相同的結果。測試它們更容易,因為它們不依賴 React。讓我們從計數器範例中取得一個reducer並使用模擬狀態對其進行測試:
test("increments the count by one", () => {
const newState = reducer({ count: 0 }, { type: "ADD" });
expect(newState.count).toBe(1)
})
useReducer()
是useState()
的替代方法,它使您可以更好地控制狀態管理並使測試更容易。所有情況都可以使用useState()
方法來完成,因此總而言之,使用您熟悉的方法,並且對您和同事來說更容易理解。
原文出處:https://dev.to/spukas/3-reasons-to-usereducer-over-usestate-43ad