大家好,我是前端理想哥,今天,我们来聊聊useState
和useReducer
的区别。
先说结论:useState和useReducer都是用于函数组件内部定义状态的,区别在于,useState用于简单的状态管理和局部状态更新,而useReducer用于复杂的状态逻辑和全局状态管理。
对于简单的状态值定义,可以用 useState,如果状态值的修改逻辑比较复杂,你想要抽离出来或者进行复用,那么就可以使用useReducer。
useState实际是一个自带了reducer功能的useReducer语法糖。
我们先来看看这两者的使用,useState的使用方法如图所示:
const [state, setState] = useState(initialState);
图中的用法大家可以看到,useState只接收一个参数,而对于initialState的取值,我们可以一起来看看useState的源码
function mountState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
const hook = mountWorkInProgressHook();
// useState的初始值
if (typeof initialState === 'function') {
initialState = initialState();
}
// 后续操作
}
大家可以看关键源码,函数一开始时候会判断 initialState
的类型,如果是 function,则会执行,然后把执行结果重新赋值给initialState。
所以,从这里我们可以看出 initialState 可以是一个具体的值,也可以是一个函数
接下来,我们看看useReducer的用法
const [state, dispatch] = useReducer(reducer, initialState, init);
对于图中的用法,大家可以看到,会接收三个参数,第一个参数是一个函数,第二个是一个初始值,第三个参数init应该很多朋友都不了解,没关系,我们通过源码来看下:
function mountReducer<S, I, A>(
reducer: (S, A) => S,
initialArg: I,
init?: I => S,
): [S, Dispatch<A>] {
const hook = mountWorkInProgressHook();
let initialState;
// useReducer的初始值
if (init !== undefined) {
initialState = init(initialArg);
} else {
initialState = ((initialArg: any): S);
}
// 后续操作
}
大家可以看关键源码,如果init参数存在,则会用init来处理初始值initialArg,然后把处理结果重新传给initialState。
所以,从这里我们可以看到 init 其实是一个函数,作用是在初始时候,对你传入的初始值进行处理的。比如你传了个初始值,但是不是你想要的,得用一个函数处理下,那你就可以把这个函数作为第三个参数传入,useReducer中会自动进行处理的。
除了上面用法的区别外,其实还有一个非常重要的区别,那就是这两者在组件更新方面的区别。
当你使用useState时,如果state没有发生变化,那么组件就不会更新。而使用了useReducer时,在state没有发生变化时,组件依然会更新。大家在使用时候,千万要注意这点的区别。
以上,就是所有内容了,我们讲了useState和useReducer的用法以及区别,如果您觉得文章对您有帮助,欢迎给理想哥一个关注,万分感谢大家