useReducer
首先創(chuàng)建一個button和n的state
import React,{useState} from "react";
import "./styles.css";
export default function App() {
const [n,setN] = useState(0)
const onClick =()=>{
setN(x=>x+1)
}
return (
<div className="App">
<h1>n: {n}</h1>
<button onClick={onClick}>+1</button>
</div>
);
}

image.png
1. 創(chuàng)建初始值initalState
const initial ={
n:0
}
2. 創(chuàng)建所有操作reducer(state,action)
const reducer = (state,action) => {
if(action.type === 'add') {
return {n:state.n+1}
} else if(action.type==='mult') {
return {n:state.n*2}
} else {
throw new Error('error')
}
}
創(chuàng)建一個帶有+1 和 *2 功能的reducer
3.將創(chuàng)建的reduder傳給userReducer得到讀寫方法
useReducer接受兩個參數(shù),一個是reducer,另一個是initial,
const [state,dispatch] = useReducer(reducer,initial)
const {n} = state
返回兩個參數(shù),一個是state保存值,另一個是dispatch

image.png
取出state中的n后,我們發(fā)現(xiàn)它就是initial中的n.和我們一開始使用的useState的值相同
4. dispatch({type:'操作方法'})
我們修改一下之前的onClick方法,調(diào)用dispatch
const onClick =()=>{
dispatch({type:'add'})
}

image.png
此時能夠看到,點擊后觸發(fā)了+1的操作,達到了之前useState的setN的效果
我們可以將加的參數(shù)傳給onClick,然后在reducer中增加傳入的參數(shù)
const reducer = (state,action) => {
if(action.type === 'add') {
return {n:state.n+action.number}
} else if(action.type==='mult') {
return {n:state.n*2}
} else {
throw new Error('error')
}
}
const onClickAdd =(number)=>{
dispatch({type:'add',number})
}
我們再創(chuàng)一個按鈕,用來做乘的操作
<button onClick={()=>onClickMult(2)}>mult * 2 </button>
修改一下reducer和onClick
const onClickMult = (number)=>{
dispatch({type:'mult',number})
}
const reducer = (state,action) => {
if(action.type === 'add') {
return {n:state.n+action.number}
} else if(action.type==='mult') {
return {n:state.n*action.number}
} else {
throw new Error('error')
}
}
先+1,在乘2

image.png
此時我們的click方法非常的簡單,因為操作被我們聚攏在reducer中,我們在click中只觸發(fā)dispatch,然后調(diào)用相對應(yīng)的reducer
通常情況下,useReducer適合用來處理表單

image.png
<form onSubmit={onSubmit} onReset={onReset}>
<div>
<label>
姓名
<input
value={formData.name}
onChange={e =>
dispatch({ type: "patch", formData: { name: e.target.value } })
}
/>
</label>
</div>
<div>
<label>
年齡
<input
value={formData.age}
onChange={e =>
dispatch({ type: "patch", formData: { age: e.target.value } })
}
/>
</label>
</div>
<div>
<label>
民族
<input
value={formData.nationality}
onChange={e =>
dispatch({
type: "patch",
formData: { nationality: e.target.value }
})
}
/>
</label>
</div>
<div>
<button type="submit">提交</button>
<button type="reset">重置</button>
</div>
<hr />
{JSON.stringify(formData)}
</form>
我們可以將reducer分為2個操作,patch(更新任意一項表單),reset(重置所有表單)
const initFormData = {
name: "",
age: 18,
nationality: "漢族"
};
function reducer(state, action) {
switch (action.type) {
case "patch":
return { ...state, ...action.formData };
case "reset":
return initFormData;
default:
throw new Error();
}
}

image.png
我們修改姓名,此時觸發(fā)patch操作