本文作者为奇舞团前端开发工程师
一. 概述
在 React16.8推出之前,我们使用react-redux
并配合一些中间件,来对一些大型项目进行状态管理,React16.8推出后,我们普遍使用函数组件来构建我们的项目,React提供了两种Hook来为函数组件提供状态支持,一种是我们常用的useState
,另一种就是useReducer
, 其实从代码底层来看useState
实际上执行的也是一个useReducer
,这意味着useReducer
是更原生的,你能在任何使用useState
的地方都替换成使用useReducer
.
Reducer
的概念是伴随着Redux
的出现逐渐在JavaScript中流行起来的,useReducer
从字面上理解这个是reducer
的一个Hook,那么能否使用useReducer
配合useContext
来代替react-redux
来对我们的项目进行状态管理呢?答案是肯定的。
二. useReducer 与 useContext
1. useReducer
在介绍useReducer
这个Hook之前,我们先来回顾一下Reducer
,简单来说 Reducer
是一个函数(state, action) => newState
:它接收两个参数,分别是当前应用的state
和触发的动作action
,它经过计算后返回一个新的state
.来看一个todoList
的例子:
export interface ITodo {
id: number
content: string
complete: boolean
}
export interface IStore {
todoList: ITodo[],
}
export interface IAction {
type: string,
payload: any
}
export enum ACTION_TYPE {
ADD_TODO = 'addTodo',
REMOVE_TODO = 'removeTodo',
UPDATE_TODO = 'updateTodo',
}
import { ACTION_TYPE, IAction, IStore, ITodo } from "./type";
const todoReducer = (state: IStore, action: IAction): IStore => {
const { type, payload } = action
switch (type) {
case ACTION_TYPE.ADD_TODO: //增加
if (payload.length > 0) {
const isExit = state.todoList.find(todo => todo.content === payload)
if (isExit) {
alert('存在这个了值了')
return state
}
const item = {
id: new Date().getTime(),
complete: false,
content: payload
}
return {
...state,
todoList: [...state.todoList, item as ITodo]
}
}
return state
case ACTION_TYPE.REMOVE_TODO: // 删除
return {
...state,
todoList: state.todoList.filter(todo => todo.id !== payload)
}
case ACTION_TYPE.UPDATE_TODO: // 更新
return {
...state,
todoList: state.todoList.map(todo => {
return todo.id === payload ? {
...todo,
complete: !todo.complete
} : {
...todo
}
})
}
default:
return state
}
}
export default todoReducer
上面是个todoList的例子,其中reducer
可以根据传入的action
类型(ACTION_TYPE.ADD_TODO、ACTION_TYPE.REMOVE_TODO、UPDATE_TODO)
来计算并返回一个新的state。reducer
本质是一个纯函数,没有任何UI和副作用。接下来看下useReducer
:
const [state, dispatch] = useReducer(reducer, initState);
useReducer
接受两个参数:第一个是上面我们介绍的reducer
,第二个参数是初始化的state
,返回的是个数组,数组第一项是当前最新的state,第二项是dispatch函数
,它主要是用来dispatch不同的Action
,从而