提供了操纵多个状态的能力,如果状态是单个的,可以是 useState 的替代。
语法:
const [state, dispatch] = useReducer(reducer, initialState)
const [state, dispatch] = useReducer(reducer, initialState, initFunction)
// 惰性地创建初始 state, 需要将 init 函数作为 useReducer 的第三个参数传入,这样初始 state 将被设置为 init(initialState)
// 或者
const [state, dispatch] = useReducer(reducer, undefined, initFunction)
示例:
import React, {useReducer, useEffect} from "react";
import ReactDOM from "react-dom";
interface State {
count: number;
step: number
}
interface Action {
type: string;
payload?: any;
}
const initialState: State = {
count: 0,
step: 1,
};
const reducer = (state: State, action: Action) => {
const {count, step} = state;
if (action.type === 'tick') {
return {count: count + step, step};
} else if (action.type === 'step') {
return {count, step: action.payload};
} else {
throw new Error();
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const {count, step} = state;
useEffect(() => {
const id = setInterval(() => {
dispatch({type: 'tick'});
}, 1000);
return () => clearInterval(id);
}, [dispatch]);
return (
<div style={{
width: '200px',
margin: '100px auto 0 auto',
textAlign: 'center',
border: '1px solid #DDD',
borderRadius: '4px',
}}>
<h1 style={{margin: '10px 0'}}>
{count}
</h1>
<input
style={{
marginBottom: '10px',
border: '1px solid #DDD',
height: '32px',
lineHeight: '32px',
borderRadius: '4px',
}}
value={step}
onChange={e => {
dispatch({
type: 'step',
payload: Number(e.target.value)
});
}}
/>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Counter/>, rootElement);