一文读懂 react 的全局状态管理

2022-12-08 0 290

react 提供更多了传模块的形式

propscontext

恒定情况下是绰绰有余的,但许多特定的情景,须要自上而下的许多状况或是兄妹模块间传参(也可能将是工程项目的某一大精明匆匆忙忙的导入了某状况管理工作苦)。上面科学研究下常见的许多状况管理工作库,如是说的是基本概念,而并非怎样采用,怎样采用技术细节见非官方文件格式。

redux

有两个基本概念要知道

Action

给这个 action 两个形式化的英文名字,比如说

“todos/todoAdded”。他们一般来说把这个类别的数组写出“域/该事件中文名称”,当中第三部份是这个 action 辖下的特点或类别,第三部份是出现的具体内容事。

Action Creator

action creator 是两个建立并回到两个 action 第三类的表达式。它的促进作用是让你无须每天都全自动撰写 action 第三类:

const addTodo = text => { return { type: todos/todoAdded, payload: text } }

Reducer

仅采用 state 和 action 模块排序捷伊状况值明令禁止间接修正 state。要透过拷贝原有的 state 并对拷贝的值展开更动的形式来做 不容更改新(immutable updates)。明令禁止任何人触发器形式论、倚赖乱数值或引致其它“过敏反应”的标识符

reducer 表达式内部的形式论一般来说遵循以下步骤:

检查 reducer 是否关心这个 action

如果是,则拷贝 state,采用新值更新 state 副本,然后回到新 state

否则,回到原来的 state 不变

不能在 Redux 中更动 state 有两个原因:

它会引致 bug,例如视图未正确更新以显示最新值更难理解状况更捷伊原因和形式撰写测试变得更加困难它打破了正确采用“时间旅行调试”的能力它违背了 Redux 的预期精神和采用模式
const initialState = { value: 0 } function counterReducer(state = initialState, action) { // 检查 reducer 是否关心这个 action if (action.type === counter/increment) { // 如果是,拷贝 `state` return { …state, // 采用新值更新 state 副本 value: state.value + 1 } } // 回到原来的 state 不变 return state }

Store

当前 Redux 应用的 state 存在于两个名为 store 的第三类中。

store 是透过传入两个 reducer 来建立的,并且有两个名为 getState 的形式,它回到当前状况值:

import { configureStore } from @reduxjs/toolkit const store = configureStore({ reducer: counterReducer }) console.log(store.getState()) // {value: 0}

Dispatch

store 将执行所有 reducer 表达式并排序出更新后的 state,调用

Selector

Selector 表达式可以从 store 状况树中提取指定的片段。随着应用变得越来越大,会遇到应用程序的不同部份须要读取相同的数据,selector 可以避免重复这样的读取形式论:

const selectCounterValue = state => state.value const currentValue = selectCounterValue(store.getState()) console.log(currentValue) // 2

在 React + Redux 应用中,你的自上而下状况应该放在 Redux store 中,你的本地状况应该保留在 React 模块中。

如果你不确定该放在哪里,这里有许多常见的经验法则,用于确定应该将哪种数据放入 Redux:

应用程序的其它部份是否关心这些数据?你是否须要能够基于这些原始数据建立进一步的派生数据?是否采用相同的数据来驱动多个模块?能够将这种状况恢复到给定的时间点(即时间旅行调试)对你是否有价值?是否要缓存数据(即,如果数据已经存在,则采用它的状况而并非重新请求它)?你是否希望在热重载视图模块(交换时可能将会丢失其内部状态)时保持此数据一致?

dva

dva 首先是两个基于 reduxredux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-routerfetch,所以也可以理解为两个轻量级的应用框架。

易学易用,仅有 6 个 api,对 redux 用户尤其友好,配合 umi 采用后更是降低为 0 APIelm 基本概念,透过 reducers, effects 和 subscriptions 组织 model插件机制,比如说dva-loading 可以自动处理 loading 状况,不用一遍遍地写 showLoading 和 hideLoading支持 HMR,基于 babel-plugin-dva-hmr 实现 components、routes 和 models 的 HMR

这个 model 里

namespace 表示在自上而下 state 上的 key

state 是初始值,在这里是空数组

reducers 等同于 redux 里的 reducer,接收 action,同步更新 state

export default { namespace: products, state: [], reducers: { delete(state, { payload: id }) { return state.filter(item => item.id !== id); }, }, };

mobox

简单,可扩展的状况管理工作

MobX区分了应用程序中的以下三个基本概念:

State(状况)

Actions(动作)

Derivations(派生)

MobX背后的基本原则

所有的 derivations 将在 state 改变时自动且原子化地更新。因此不容能观察中间值。

所有的 derivations 默认将会同步更新,这意味着 action 可以在 state 改变 之后安全的间接获得 computed 值。

computed value 的更新是惰性的,任何人 computed value 在须要他们的过敏反应出现之前都是不激活的。

所有的 computed value 都应是纯表达式,他们不应该修正 state。

umi 的 useModel

@umi/max 内置了数据流管理工作插件,它是一种基于

hooks 范式的轻量级数据管理工作方案,可以在 Umi 工程项目中管理工作自上而下的共享数据

建立model

数据流管理工作插件采用约定式目录结构,他们约定可以在 src/models, src/pages/xxxx/models/目录中,和 src/pages/xxxx/model.{js,jsx,ts,tsx} 文件导入 Model 文件。 Model 文件允许采用 .js,.jsx,.ts 和 .tsx 四种后缀格式,命名空间(namespace) 生成规则如下。

路径命名空间说明src/models/count.tscountsrc/models目录下不支持目录嵌套定义 modelsrc/pages/pageA/model.tspageA.modelsrc/pages/pageB/models/product.tspageB.productsrc/pages/pageB/models/fruit/apple.tspageB.fruit.applepages/xxx/models下 model 定义支持嵌套定义

采用 model

import { useModel } from umi; export default () => { const { add, minus } = useModel(counterModel, (model) => ({ add: model.increment, minus: model.decrement, })); return ( <div> <button onClick={add}>add by 1</button> <button onClick={minus}>minus by 1</button> </div> ); };

自上而下状况

@umi/max 内置了自上而下初始状况管理工作插件

自上而下初始状况是一种特定的 Model。

自上而下初始状况在整个 Umi 工程项目的最开始建立。撰写 src/app.ts 的导出形式 getInitialState(),其回到值将成为自上而下初始状况

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务