先来看官网解释:
useState
的替代方案。它接收一个形如(state, action) => newState
的 reducer,并返回当前的 state 以及与其配套的dispatch
方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)
在某些场景下,useReducer
会比useState
更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用useReducer
还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递dispatch
而不是回调函数
useReducer使用语法为:
const [state, dispatch] = useReducer(reducer, initialArg, init);
看一个使用 reducer 写计数器的示例:
import { useRef,useReducer} from "react";
import * as ReactDOM from "react-dom";
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
可以看到,跟使用redux的形式一样。
来看看第三个参数init的使用:
import { useRef,useReducer} from "react";
import * as ReactDOM from "react-dom";
function init(initialCount) {
return {count: initialCount};
}
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
case 'reset':
// init()返回的同上面case一样都是最终的state,所以通常useReducer并不一定需要第三个参数init,否则还容易混淆视听。
return init(action.payload);
default:
throw new Error();
}
}
function App({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}>
Reset
</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App initialCount={0} />, rootElement);
总的来说,useReducer是在某些复杂state和state逻辑处理复杂的场景中用来替代useState的。