前言
useReducer
使用useReducer写一个表单提交的案例
使用useReducer代替Redux
前面已经介绍了useState 的详细用法,我们可以在函数组件和类组件中使用 useState 来创建变量和对象。使得页面能够及时的更新 UI 等等。接下来介绍一个 useState 的复杂版本–useReducer
useReducer 是 useState 的升级版本,用来践行 Flux/Redux 的思想
它主要有两个参数,一个读接口 state,一个写接口 dispatch
要自己先定义好 state 状态量和 setState 的一些函数 API
参数列表:
useReducer(dispatch,state,init)
在页面中显示 n 的值,且按下按钮后会触发响应的操作使 n 值发生变化。其中的操作分别是使 n+1,n+2,nx2。
const initialState = {
n: 0,
};
const reducer = (state, action) => {
if (action.type === "add") {
/* 规则与useState一样必须返回新的对象,不然变量值不会改变 */
return {
n: state.n + action.number };
} else if (action.type === "multi") {
return {
n: state.n * action.number };
} else {
throw new Error("unknown type!");
}
};
/* 在函数组件中使用useReducer */
const App = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const onclick1 = () => {
dispatch({
type: "add", number: 1 });
};
const onclick2 = () => {
dispatch({
type: "add", number: 2 });
};
const onclick3 = () => {
dispatch({
type: "multi", number: 2 });
};
return (
<div className="App">
<h1>n:{
state.n}</h1>
<button onClick={
onclick1}>+1</button>
<button onClick={
onclick2}>+2</button>
<button onClick={
onclick3}>x2</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
效果展示
在对+1、+2、x2 按钮一番按键后,改变了页面中的 n 值。
用法与 useState 类似,从 useReducer 中得到读接口 state,写接口 dispatch。最后操作时传参给 dispatch 写接口。操作灵活多变,比 useState 好处就是能聚集所有的操作和各种状态量。着重理解这几行代码,读懂。
useReducer 算是 useState 的复杂版
使用 useReducer 分以下步骤:
创建初始值的状态initialState
创建所有对状态的操作reducer(state,action)
传给useReducer,得到读和写的接口
调用写({'type':'操作类型'})
写一个简单的表单,包含姓名,年龄,民族等信息。在下方显示输入表单的值的动态变化
const initialState = {
name: "",
age: 18,
nationality: "汉族",
};
const reducer = (state, action) => {
switch (action.type) {
case "patch":
return {
...state, ...action.formData };
case "reset":
return initialState;
default:
throw new Error("unknown type!");
}
};
/* 在函数组件中使用useReducer */
const App = () => {
const [formData, dispatch] = useReducer(reducer, initialState);
const onSubmit = () => {
alert("你点击了提交按钮");
};
const onReset = () => {
dispatch({
type: "reset" });
};
return (
<form onSubmit={
onSubmit} onReset={
onReset}>
<div>
<label>
姓名
<input
type="text"
value={
formData.name}
onChange={
(e) => {
dispatch({
type: "patch", formData: {
name: e.target.value } });
}}
/>
</label>
</div>
<div>
<label>
年龄
<input
type="number"
value={
formData.age}
onChange={
(e) => {
dispatch({
type: "patch", formData: {
name: e.target.value } });
}}
/>
</label>
</div>
<div>
<label>
民族
<input
type="text"
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>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
效果展示
我随意在输入框中输入一些东西,下面会及时的更新显示出来的输入的数据
使用 createContext/useContext 模拟 Redux 的全局数据状态管理的作用域,useReducer 来表示全局数据状态管理中的所有读写操作。
在创建的上下文对象中能够及时更新数据,就类似于一个局部的 Redux。在以下代码中,案例
:我将模拟一个 state 有三个变量 n,m,p。一个组件更新,其他组件的值也会连带着更新。
const store = {
n: 0,
m: 0,
p: 0,
};
const reducer = (state, action) => {
switch (action.type) {
case "setN":
return {
...state, n: state.n + action.number };
case "setM":
return {
...state, m: state.m + action.number };
case "setP":
return {
...state, p: state.p + action.number };
default:
throw new Error("unknown type!");
}
};
/* 创建上下文对象--模拟一个Redux的作用域 */
const Context = React.createContext(null);
const App = () => {
const [state, dispatch] = React.useReducer(reducer, store);
return (
<Context.Provider value={
{
state, dispatch }}>
<N />
<M />
<P />
</Context.Provider>
);
};
const N = () => {
const {
state, dispatch } = React.useContext(Context);
const addClick = () => {
dispatch({
type: "setN", number: 1 });
};
return (
<div>
<h1>N组件</h1>
<div>n:{
state.n}</div>
<div>m:{
state.m}</div>
<div>p:{
state.p}</div>
<button onClick={
addClick}>+1</button>
</div>
);
};
const M = () => {
const {
state, dispatch } = React.useContext(Context);
const addClick = () => {
dispatch({
type: "setM", number: 2 });
};
return (
<div>
<h1>M组件</h1>
<div>n:{
state.n}</div>
<div>m:{
state.m}</div>
<div>p:{
state.p}</div>
<button onClick={
addClick}>+2</button>
</div>
);
};
const P = () => {
const {
state, dispatch } = React.useContext(Context);
const addClick = () => {
dispatch({
type: "setP", number: 3 });
};
return (
<div>
<h1>P组件</h1>
<div>n:{
state.n}</div>
<div>m:{
state.m}</div>
<div>p:{
state.p}</div>
<button onClick={
addClick}>+3</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
效果展示
在一番对 n,m,p 数据的操作后,所有组件的值都变化了更新
...state
拷贝原先的数据,在覆写要修改的数据。原因:【React 全解 1 state&setState】