导读:使用useReducer可以减少useState的使用,减少VDOM的render次数,也便于统一管理多变量
了解useReducer()
这个hooks
之前,首先得了解redux
。redux
中的reducer,dispatch,action,store
概念。
关于redux的概念,推荐阅读这篇wiki:https://www.redux.org.cn/docs/basics/
在开发过程中,登录页面很常见,那么在函数组件中,如何使用hooks
来编码实现呐?首先我们先看看第一个版本:
// 省略了部分代码 const React, { useState } = require("react") const loginPage = () => { const [name, setName] = useState(''); const [pwd, setPwd] = useState(''); const [isLoading, setIsLoading] = useState(false); const [errorMsg, setErrorMsg] = useState(''); const [isLoggedIn, setIsLoggedIn] = useState(false); const login = (event) => { event.preventDefault(); event.stopPropagation(); setIsLoading(true); setErrorMsg(''); loginApi({name, pwd}).then(() => { // success setIsLoggedIn(true); }).catch(err => { // error setErrorMsg(err.message); setName(''); setPwd(''); }).finally(() => { setIsLoading(false); }); }; return ( <div> <div>{isLoggedIn ? "已登录" : "未登录"}</div> <button onClick={(e) => login(e)}>点击登录</button> <div>{errorMsg}</div> {isLoading ? <div>loading....</div> : ""} </div> ); }
大家发现,使用useState
我们需要维护很多的变量,不停地使用setXxxx()
去更新变量值。当另一个同事想接手你的代码时,发现这代码简直在后期无法维护,在判断逻辑中,倘若某个变量疏忽,就会产生错误,有什么方法可以将变量的赋值整合在一起呐?
当然有!React
官方提供了useReducer
这个hooks
,就像使用redux
状态管理一下使用即可,那么接下来看看第二个版本的代码:
import React, { useReducer } from "react"; import ReactDOM from "react-dom"; const initialState = { name: "", pwd: "", isLoading: false, errorMsg: "", isLoggedIn: false, }; const loginReducer = (state = initialState, action) => { switch (action.type) { case "login": return { ...state, isLoading: true, errorMsg: "", isLoggedIn: false, }; case "success": return { ...state, isLoading: false, isLoggedIn: true, }; case "error": return { ...state, isLoading: false, errorMsg: action.payload.msg, name: "", pwd: "", isLoggedIn: false, }; default: return state; } }; // 模拟网络请求登录数据的API const loginApi = (username, password) => { return new Promise((resolve, reject) => { setTimeout(() => { const isError = Math.round(Math.random() * 100) % 2; if (isError) { reject({ code: 400, message: "登录失败", }); } else { resolve({ code: 200, }); } }, 3000); }); }; function Example() { const [state, dispatch] = useReducer(loginReducer, initialState); const { name, pwd, isLoading, errorMsg, isLoggedIn } = state; const login = (event) => { event.preventDefault(); event.stopPropagation(); dispatch({ type: "login" }); loginApi({ name, pwd }) .then(() => { // success dispatch({ type: "success" }); }) .catch((err) => { // error dispatch({ type: "error", payload: { msg: err.message } }); }); }; return ( <div> <div>{isLoggedIn ? "已登录" : "未登录"}</div> <button onClick={(e) => login(e)}>点击登录</button> <div>{errorMsg}</div> {isLoading ? <div>loading....</div> : ""} </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<Example />, rootElement);
你会感到疑惑,第二个版本的代码的行数不是更多了么,难道不是更复杂了吗?答案当然是更简单了,除去一些DOM
挂载代码,我们可以发现主要的逻辑采用dispatch
来维护,有变量的改变,只需要在loginReducer
中统一修改,大大地提升了可维护性。
上一篇
Flex布局
Flex布局
版权声明:《 为什么要使用React中的useReducer 》为DYBOY原创文章,转载请注明出处!
最后编辑:2020-8-29 15:08:42
2020-12-29 14:13
如果是地中方案是不是可以用受控组件获取name和pwd的值
过时第二种方案是不是加上在设置initialState的时候就用useRef关联上,如果代码全了。简直完美。。。
2020-09-03 11:11
2020-08-29 15:54
参考中文官方文档:https://zh-hans.reactjs.org/docs/context.html
使用经验:
- 如果你的页面state很简单,可以直接使用useState
- 如果你的页面state比较复杂(state是一个对象或者state非常多散落在各处)请使用userReducer
- 如果你的页面组件层级比较深,并且需要子组件触发state的变化,可以考虑useReducer + useContext