前言:最近接触到一种新的(对我个人而言)状态管理方式,它没有采用现有的开源库,如redux、mobx等,也没有使用传统的useContext,而是用useState + useEffect写了一个发布订阅者模式进行状态管理,这一点对我来说感觉比较新奇,以前从没接触过这种写法,于是决定研究一下目前比较常用的状态管理方式。
ps:这里谈到的状态管理是指全局状态管理,局部的使用useState即可
状态管理方式
目前比较常用的状态管理方式有hooks、redux、mobx三种,下面我将详细介绍一下这三类的使用方法以及分析各自的优缺点,以供各位进行参考。
Hooks状态管理
用hooks进行状态管理主要有两种方式:
- useContext+useReducer
- useState+useEffect
useContext+useReducer
使用方法
1.创建store和reducer以及全局context
src/store/reducer.ts
import React from "react";
// 初始状态
export const state = {
count: 0,
name: "ry",
};
// reducer 用于修改状态
export const reducer = (state, action) => {
const {
type, payload } = action;
switch (type) {
case "ModifyCount":
return {
...state,
count: payload,
};
case "ModifyName":
return {
...state,
name: payload,
};
default: {
return state;
}
}
};
export const GlobalContext = React.createContext(null);
2.根组件通过 Provider 注入 context
src/App.tsx
import React, {
useReducer } from "react";
import './index.less'
import {
state as initState, reducer, GlobalContext} from './store/reducer'
import Count from './components/Count'
import Name from './components/Name'
export default function () {
const [state, dispatch] = useReducer(reducer, initState);
return (
<div>
<GlobalContext.Provider value={
{
state, dispatch}}>
<Count />
<Name />
</GlobalContext.Provider>
</div>
)
}
3.在组件中使用
src/components/Count/index.tsx
import {
GlobalContext } from "@/store/reducer";
import React, {
FC, useContext } from "react";
const Count: FC = () => {
const ctx = useContext(GlobalContext)
return (
<div>
<p>count:{
ctx.state.count}</p>
<button onClick={
() => ctx.dispatch({
type: "ModifyCount", payload: ctx.state.count+1 })}>+1</button>
</div>
);
};
export default Count;
src/components/Name/index.tsx
import {
GlobalContext } from "@/store/reducer";
import React, {
FC, useContext } from "react";
const Name: FC = () => {
const ctx = useContext(GlobalContext)
console.log("NameRerendered")
return (
<div>
<p>name:{
ctx.state.name}</p>
</div>
);
};
export default Name;
useState+useEffect
使用方法
1.创建state和reducer
src/global-states.ts
// 初始state
let globalState: GlobalStates = {
count: 0,
name: 'ry'
}
// reducer
export const modifyGlobalStates = (
operation: GlobalStatesModificationType, payload: any
) => {
switch (operation) {
case GlobalStatesModificationType.MODIFY_COUNT:
globalState = Object.assign({
}, globalState, {
count: payload })
break
case GlobalStatesModificationType.MODIFY_NAME:
globalState = Object.assign({
}, globalState, {
name: payload })
break
}
broadcast