redux设计理念
状态管理现在不应该解决吗? 凭直觉,开发人员似乎知道一个隐藏的事实:状态管理似乎比其需要的困难。 在本文中,我们将探讨您可能一直在问自己的一些问题:
- 您需要用于状态管理的库吗?
- Redux的受欢迎程度值得吗? 为什么或者为什么不?
- 我们可以制定更好的状态管理解决方案吗? 如果是这样,怎么办?
国家管理需要图书馆吗?
成为前端开发人员不仅要四处移动像素。 开发的真正艺术是知道将状态存储在哪里。 简短的答案:这很复杂,但并不那么复杂。
让我们看看使用像React这样基于组件的视图框架/库时的选项:
1.组件状态
存在于单个组件内部的状态。 在React中,认为state
已用setState
更新。
2.相对状态
国家由父母传给孩子。 在React中,认为props
作为子组件的属性传递。
3.提供状态
处于根提供者中的状态 , 消费者可以在组件树下的某个位置访问它,而不管其邻近程度如何。 在React中,考虑context API
。
视图中反映了UI,因此它属于很多状态。 但是其他所有反映您的基础数据和逻辑的代码又如何呢?
将所有内容放入视图中可能导致关注点分离不良:它将您与javascript视图库联系在一起,使代码更难测试,甚至可能带来最大的烦恼:您必须不断思考并重新调整存储状态的位置。
由于设计会发生变化,因此状态管理变得很复杂,通常很难确定哪些组件将需要哪个状态。 最直接的选择是只提供根组件的所有状态,这时最好选择下一个选项。
4.外部状态
可以将状态移出视图库。 然后,库可以使用提供者/消费者模式“连接”以保持同步。
也许最受欢迎的状态管理库是Redux。 在过去的两年中,它的受欢迎程度大大提高。 那么,为什么对一个简单的图书馆如此钟情?
Redux的性能更高吗? 否。必须处理的每个新操作都会稍微慢一点。
Redux更简单吗? 当然不是。
简单的将是纯JavaScript:
那么,为什么每个人都不只是使用global.state = {}
?
为什么要使用Redux?
在后台,Redux实际上与TJ的根对象相同-仅包装在实用程序管道中。
在Redux中,您不能直接修改状态。 只有一种方法: 将 操作 分派到最终更新状态的管道中。
沿途有两套侦听器: 中间件和订阅 。 中间件 是可以侦听传入动作的函数,从而启用诸如“记录器”,“ devtools”或“ syncWithServer”侦听器之类的工具。 订阅内容 是用于广播这些状态更改的功能。
最后, Reducer更新了可以将状态更改分解为更小,更模块化和可管理的块的功能。
与将全局对象作为状态相比,Redux实际上可能更易于开发。
将Redux视为具有更新前/更新后钩子的全局对象,以及简化的“减少”下一个状态的方式。
但是Redux不太复杂吗?
是。 有几个不可否认的迹象表明需要改进的API。 这些可以用以下等式总结:
考虑一下time_saved
来表示您可能花费在开发自己的解决方案上的时间,而time_invested
等于在阅读文档,学习教程和研究陌生概念上花费的时间。
Redux本质上是一个简单而小型的库,学习曲线陡峭。 对于每个克服Redux并从中受益的开发人员来说,他们都深深地学习了函数式编程,因此又有一个潜在的开发人员迷失了方向,认为“这不适合我,我要回到jQuery”。
您不需要了解使用jQuery的“概念”,也不必理解功能组合来处理状态管理。
任何库的目的 都是 通过抽象 使 看起来 更 简单的 事情变得 简单。
需要明确的是,我的意图不是诱骗Dan Abramov。 Redux在婴儿期太早变得太流行了。
- 您如何重构已经被数百万开发人员使用的库?
- 您如何证明发布影响全球无数项目的重大更改的合理性?
你不能 但是,您可以通过广泛的文档,教育视频和社区扩展来提供出色的支持。 丹·阿布拉莫夫(Dan Abramov)在这里赢得了胜利。
也许还有另一种方式。
重新设计Redux
我认为Redux应该重写。 我准备了7个需要改进的地方。
1.设定
让我们看一下左侧真实世界 Redux示例中的基本设置。
在第一步之后,许多开发人员在这里停了下来,呆呆地呆在深渊中。 什么是笨蛋 ? 组成 ? 函数可以做到吗?
考虑Redux是否基于配置而非合成。 安装程序看起来更像右侧的示例。
2.简化的减速器
Redux中的reducers可以使用一个开关来摆脱我们过去习惯的冗长的switch语句。
假设化简器在操作类型上匹配,我们可以反转参数,以便每个化简器都是接受状态和操作的纯函数。 甚至更简单,我们可以标准化动作并仅传递状态和有效负载。
4.异步/等待暴徒
Thunk通常用于在Redux中创建异步操作。 从许多方面来看,重击的工作方式似乎更像是一个巧妙的技巧,而不是正式推荐的解决方案。 在这里关注我:
- 您分派一个动作,它实际上是一个函数,而不是预期的对象。
- Thunk中间件检查每个动作,以查看它是否是一个功能。
- 如果是这样,中间件将调用该函数并传递对某些存储方法的访问:dispatch和getState。
真? 将简单的动作动态地键入为对象,函数或Promise,这不是坏习惯吗?
就像右边的例子一样,我们不能只是异步/等待吗?
5.两种动作
考虑一下,实际上有两种动作:
- 减速器动作 :触发减速器并更改状态。
- 效果动作 :触发异步动作。 这可能会调用Reducer操作,但是异步函数不会直接更改任何状态。
区分这两种类型的动作将更加有用,并且不会使上述用法与“ thunks”混淆。
6.没有更多的动作类型作为变量
为什么按标准惯例对待动作创建者和减少者有区别? 一个可以没有另一个存在吗? 改变一个不会影响另一个吗?
动作的创造者和还原者是同一枚硬币的两个方面。
const ACTION_ONE = 'ACTION_ONE'
是动作创建者和简化者分离的多余副作用。 将两者视为一个,不再需要导出类型字符串的大文件。
7.减速器是动作的创造者
通过按用途对Redux的元素进行分组,您很可能会想到一个更简单的模式。
可以从化简器自动确定动作创建者。 毕竟,在这种情况下,reducer可以成为动作创建者 。
使用基本的命名约定,以下是可以预见的:
- 如果减速器的名称为“ increment”,则类型为“ increment”。 更好的是,让我们对其命名空间:“计数/增量”。
- 每个动作都通过“有效载荷”键传递数据。
现在,从count.increment
我们可以仅从化count.increment
器生成动作创建者。
好消息:我们可以有更好的Redux
这些痛点是我们创建Rematch的原因。
Rematch是Redux的包装器,它提供了一个更简单的API,而不会丢失任何可配置性。
请参见下面的完整“重赛”示例:
在过去的几个月中,我一直在生产中使用Rematch。 作为推荐,我会说:
我从来没有花太多时间思考状态管理。
Redux不会消失,也不应该消失。 以更少的学习曲线,更少的样板和更少的认知开销来拥抱Redux背后的简单模式。
尝试Rematch ,看看您是否不喜欢它。
并给我们一颗星星,让其他人知道您的行为。
redux设计理念