redux ngrx

by Andrey Goncharov

通过安德烈·贡恰洛夫(Andrey Goncharov)

另一个减少Redux(NGRX)应用程序样板的指南 (Yet another guide to reduce boilerplate in your Redux (NGRX) app)

我们在这里要覆盖什么? (What are we gonna cover here?)

In this article, we’re gonna discuss several ways/tips/tricks/ancient black magic rituals to reduce boilerplate in our overwhelmed-with-boilerplate Redux (and NGRX!) apps. I’ve come up with these over the years from first-hand production experience.

在本文中,我们将讨论几种方法/技巧/技巧/古老的黑魔法仪式,以减少我们不堪重负的Redux(和NGRX!)应用程序中的样板。 这些年来,我已经从第一手生产经验中提出了这些建议。

Let me be honest with you all. I wanted to speak just about my new micro-library flux-action-class at first. But it seems like sometimes tech blogs look more and more like Twitter lately…and maybe you want some more meaningful long read. So I thought: “What the heck? I got some experience and best practices of my own which I spilled some sweat and blood over. Maybe, it could help some people out there. Maybe, people out there could help me to improve some of it.”

让我对你们所有人诚实。 首先,我只想谈谈我的新微库通量作用课程 。 但是似乎有时候高科技博客最近看起来越来越像Twitter……也许您想要一些更有意义的长期阅读。 所以我想:“到底是什么? 我获得了一些自己的经验和最佳实践,这让我不知所措。 也许,它可以帮助一些人。 也许,在那里的人可以帮助我改善其中的一些。”

识别样板 (Identifying boilerplate)

Let’s take a look at a typical example of how to make AJAX requests in Redux. In this particular case let’s imagine we wanna get a list of cats from the server.

让我们看一下如何在Redux中进行AJAX请求的典型示例。 在这种特殊情况下,让我们想象一下我们想要从服务器中获取猫的列表。

If you’re wondering why I have selector factories (makeSelector…) take a look here

如果您想知道为什么我有选择器工厂(makeSelector ...),请看这里

I’m leaving out side effect handling on purpose. It’s a topic for a whole different article full of teenager’s anger and criticism for the existing ecosystem :D

我没有故意处理副作用。 这是整个不同文章的主题,充满了青少年对现有生态系统的愤怒和批评:D

This code has several weak spots:

这段代码有几个弱点:

  • Action creators are unique objects themselves but we still need action types for serialization purposes. Could we do better?动作创建者本身就是唯一的对象,但是出于序列化的目的,我们仍然需要动作类型。 我们可以做得更好吗?
  • As we add entities we keep duplicating the same logic for flipping loading flag. Actual server data and the way we want to handle it may change, but logic for loading is always the same. Could we get rid of it?

    当我们添加实体时,我们将重复相同的逻辑以翻转loading标志。 实际的服务器数据以及我们要处理的数据方式可能会发生变化,但是loading逻辑始终是相同的。 我们可以摆脱它吗?

  • Switch statement is O(n) (which is not a solid argument by itself because Redux is not very performant anyway). Redux requires a couple extra lines of code for each case and switches can not be easily combined. Could we figure out something more performant and readable?Switch语句为O(n)(它本身不是一个可靠的参数,因为Redux并不是很有效)。 Redux在每种情况下都需要额外的几行代码,并且开关无法轻松组合。 我们能找出一些更高性能和可读性的东西吗?
  • Do we really need to keep an error for each entity separately?我们真的需要为每个实体单独保留一个错误吗?
  • Using selectors is a good idea. This way we have an abstraction over our store and can change its shape without breaking the whole app by just adjusting our selectors. Yet we have to create a factory for each selector due to how memoizaion works. Is there any other way?使用选择器是一个好主意。 这样,我们可以对商店进行抽象处理,并且可以通过调整选择器来更改其形状而不会破坏整个应用程序。 然而,由于记忆的工作原理,我们必须为每个选择器创建一个工厂。 还有其他办法吗?

提示1:摆脱动作类型 (Tip 1: Get rid of action types)

Well, not really. But we can make JS generate them for us!

好吧,不是真的。 但是我们可以让JS为我们生成它们!

Let’s take a minute here to think why we even need action types. Of course, to help the reducer somehow differentiate between incoming actions and change our state accordingly. But does it really have to be a string? If only we had a way to create objects (actions) of certain types… Classes to the rescue! We most definitely could use classes as action creators and do switch by type. Like this:

让我们在这里花点时间思考为什么我们甚至需要动作类型。 当然,为了帮助减速器以某种方式区分进来的动作并相应地更改我们的状态。 但这真的必须是字符串吗? 如果只有一种方法可以创建某些类型的对象(动作),那么就可以救援了! 我们绝对可以将类用作动作创建者,并按类型进行switch 。 像这样:

All good, but here’s a thing… We can no longer serialize and deserialize our actions. They are no longer simple objects with a prototype of Object. All have unique prototypes which actually makes switching over action.constructor work. Dang, I liked the idea of serializing my actions to a string and attaching it to bug reports. So could we do even better?

一切都很好,但是这里有件事……我们不能再序列化和反序列化我们的操作。 它们不再是带有对象原型的简单对象。 它们都有独特的原型,实际上使切换action.constructor起作用。 Dang,我喜欢将操作序列化为字符串并将其附加到错误报告的想法。 那我们还能做得更好吗?

Actually, yes! Luckily each class has a name, which is a string, and we could utilize them. So for the purposes of serialization, each action needs to be a simple object with field type (please, take a look here to learn what else any self-respecting action should have). We could add getter type to each one of our classes which would use class's name.

其实,是! 幸运的是,每个类都有一个名称,它是一个字符串,我们可以利用它们。 因此,出于序列化的目的,每个动作都必须是一个具有字段type的简单对象(请在这里看看,以了解其他任何自重动作应该具有的内容)。 我们可以将getter type添加到我们每个使用类名称的类中。

It would work, but this way we can not prefix our action types as this great proposal suggests (actually, I like its successor even more). To work around prefixing we should stop using class’ name directly and create another getter for it. This time a static one.

它将起作用,但是通过这种方式,我们不能像这个好建议所建议的那样在操作类型前加上前缀(实际上,我更喜欢它的后继者 )。 要解决前缀问题,我们应该停止直接使用类的名称,并为其创建另一个getter。 这次是静态的。

Let’s polish it a little to avoid code duplication and add one more assumption to reduce boilerplate even further. If action is an error action payload must be an instance of Error.

让我们对其进行完善,以避免代码重复,并增加一个假设以进一步减少样板。 如果action是一个错误操作,那么payload必须是Error一个实例。

At this point, it works perfectly with NGRX. Redux is complaining about dispatching non-plain objects (it validates the prototype chain). Fortunately, JS allows us to return an arbitrary value from the constructor and we do not really need our actions to have a prototype.

此时,它可以与NGRX完美配合。 Redux抱怨调度非普通对象(它验证了原型链)。 幸运的是,JS允许我们从构造函数中返回任意值,并且我们实际上不需要采取行动就可以拥有原型。

Not to make you guys copy-paste ActionStandard class and worry about its reliability, I created a small library called flux-action-class, which already has all that code covered with tests with 100% code coverage, written in TypeScript for TypeScript and JavaScript projects.

为了ActionStandard你们复制粘贴ActionStandard类并担心它的可靠性,我创建了一个名为flux-action-class的小型库 ,该库已经包含了用100%代码覆盖率进行测试的所有代码,并使用TypeScript为TypeScript和JavaScript编写项目。

提示2:组合减速机 (Tip 2: Combine your reducers)

The idea is simple: use combineReducers not only for top level reducers, but for combining reducers for loading and other stuff. Let the code speak for itself:

这个想法很简单:不仅可以将CombineReducers用于顶级减速器,而且可以将减速器组合用于loading和其他东西。 让代码说明一切:

提示3:切换开关 (Tip 3: Switch away from switch)

Use objects and pick from them by key instead! Picking a property of an object by key is O(1) and it looks much cleaner if you ask me. Like this:

使用对象并通过键从中选择! 通过键选择对象的属性为O(1),如果您问我,它看起来更干净。 像这样:

I suggest we refactor reducerLoading a little bit. With the introduction of reducer maps, it makes sense to return a reducer map from reducerLoading. We could extend it if needed (unlike switches).

我建议我们重构reducerLoading一点。 通过引入reducer映射,从reducerLoading返回一个reducer映射是reducerLoading 。 如果需要,我们可以扩展它(与开关不同)。

Redux’s official documentation mentions this, but for some reason, I saw lots of people still using switch-cases. There’s already a library for createReducer. Do not hesitate to use it.

Redux的官方文档中提到了这一点 ,但是由于某些原因,我看到很多人仍在使用开关盒。 已经有一个createReducer 库 。 不要犹豫,使用它。

提示4:拥有全局错误处理程序 (Tip 4: Have a global error handler)

It’s not necessary to keep an error for each entity. In most cases, we need to display an error dialog or something. The same error dialog for all them!

不必为每个实体都保留一个错误。 在大多数情况下,我们需要显示错误对话框或其他内容。 他们所有的错误对话框都一样!

Create a global error handler. In the most simple case it could look like this:

创建一个全局错误处理程序。 在最简单的情况下,它可能看起来像这样:

Then in your side-effect’s catch block dispatch ErrorInit. It could look like this with redux-thunk:

然后在副作用的catch块中调度ErrorInit 。 使用redux-thunk可能看起来像这样:

Then you could stop providing a reducer for error part of cats' state and CatsGetError just to flip loading flag.

然后,您可以停止为猫的状态和CatsGetError error部分提供化CatsGetError ,以翻转loading标志。

提示5:停止记忆所有内容 (Tip 5: Stop memoizing everything)

Let’s take a look at a mess we have with selectors one more time. I omitted makeSelectorCatsError because of what we discovered in the previous section.

让我们再来看一次与选择器的混乱情况。 由于我们在上一节中发现了什么,所以我省略了makeSelectorCatsError

Why would we create memoized selectors for everything? What’s there to memoize? Picking an object’s field by key (which is exactly what’s happening here) is O(1). Just write a regular non-memoized function. Use memoization only when you want to change the shape of the data in your store in a way that requires non-constant time before returning it to your component.

为什么我们要为所有内容创建记忆选择器? 有什么要记住的? 通过键选择对象的字段(这正是此处发生的情况)为O(1)。 只需编写一个常规的非记忆函数即可。 仅当您要更改存储中数据的形状而又需要非常长时间才能将其返回到组件之前,才使用备忘录。

Memoization could make sense only if computed some derived data. For this example let’s imagine that each cat is an object with field name and we need a string containing names of all cats.

只有计算了一些派生数据,记忆化才有意义。 对于此示例,我们假设每只猫都是一个具有字段name的对象,并且我们需要一个包含所有猫的名称的字符串。

结论 (Conclusion)

Let’s take a look at what we started with:

让我们看一下我们的开始:

And what the result is:

结果是:

Hopefully, you found something useful for your project. Feel free to communicate your feedback to me! I most certainly appreciate any criticism and questions.

希望您发现了一些对您的项目有用的东西。 随时向我传达您的反馈! 我当然很感谢任何批评和疑问。

翻译自: https://www.freecodecamp.org/news/yet-another-guide-to-reduce-boilerplate-in-your-redux-ngrx-app-3794a2dd7bf/

redux ngrx

redux ngrx_另一个减少Redux(NGRX)应用程序样板的指南相关推荐

  1. Redux你的Angular 2应用--ngRx使用体验

    Angular2和Rx的相关知识可以看我的Angular 2.0 从0到1系列 第一节:Angular 2.0 从0到1 (一) 第二节:Angular 2.0 从0到1 (二) 第三节:Angula ...

  2. 设计实现优雅修改redux数据流的一个库 - redux-chef

    前言 首先呢~ 在分享前先贴上我写的redux-chef源码,大家如有兴趣可以阅读:redux-chef 背景:麻烦的redux社区规范 在使用redux很久以后,有一天写着写着,突然觉得action ...

  3. [Redux/Mobx] 什么是redux?说说你对redux的理解?有哪些运用场景?

    [Redux/Mobx] 什么是redux?说说你对redux的理解?有哪些运用场景? Redux是一个数据管理的库,它除了将数据存储在单一数据源中之外,还确定了变更数据.读取数据的方式,以此来明确了 ...

  4. Redux学习(一)——Redux的使用过程

    一.为什么需要redux JavaScript开发的应用程序,已经变得越来越复杂了: JavaScript需要管理的状态越来越多,越来越复杂: 这些状态包括服务器返回的数据.缓存数据.用户操作产生的数 ...

  5. Redux相关知识(什么是redux、redux的工作原理、redux的核心概念、redux的基本使用)(十一)

    系列文章目录 第一章:React基础知识(React基本使用.JSX语法.React模块化与组件化)(一) 第二章:React基础知识(组件实例三大核心属性state.props.refs)(二) 第 ...

  6. Redux入门0x101: 简介及`redux`简单实现

    0x000 概述 这一章开始讲redux,其实是承接前面的react,但其实作为一个框架来说,redux和react并没有太多的关系,本身是独立存在的.在我看来它们的关系不会比共用re开头更深了,所以 ...

  7. Delphi XE5实现减少编译出来的程序体积

    本文章介绍了Delphi XE5实现减少编译出来的程序体积,一般情况下,编译出来的文件会比较大,对于发布来说,比较不方便,经过查询,找到了两个减少体积的办法 1:关闭DEBUG信息,通过下面的步骤来实 ...

  8. 大厂面试:一个四年多经验程序员的BAT面经(字节、阿里、腾讯)

    大厂面试:一个四年多经验程序员的BAT面经(字节.阿里.腾讯) 目录 背景 说明 字节面经 面试题 腾讯面经 面试题 阿里Lazada 面试题 经验之谈 1.首要条件:准备好基础的八股文 2.常用的中 ...

  9. 一个完整的Installshield安装程序实例

    一个完整的Installshield安装程序实例-艾泽拉斯之海洋女神出品(一)---基本设置一 前言 Installshield可以说是最好的做安装程序的商业软件之一,不过因为功能的太过于强大,以至于 ...

最新文章

  1. boost::container实现前向迭代的测试程序
  2. QT的QMultiMap类的使用
  3. Linux 查看某一个进程占用内存情况
  4. chm帮助文档出现乱码
  5. 调用其他app 的lib_ButterKnife执行效率为什么比其他注入框架高?它的原理是什么...
  6. 运动基元_Java更快地对基元数组进行排序?
  7. nginx php exec,PHP Web 端如何操作 Nginx 配置
  8. 【时间统计】windows/linux 获取本地时间(精确到微妙)
  9. 三大运营商回复 4G 降速;微信上线语音转文字功能;IntelliJ IDEA 2019.2.1 发布 | 极客头条...
  10. 【C语言项目设计】趣味算术游戏设计
  11. 万能的应用商店_WiFi万能助手
  12. Hutool PinyinException: No pinyin jar found Please add one of it to your project问题解决
  13. 苹果付费app共享公众号_8.10号,IOS苹果App Store 5款付费App限时免费,支持iPhone/iPad...
  14. Photoshop 渐变工具使用
  15. 求n重幂详细过程代码及思路(java)
  16. 16年,平凡而又收获的一年,android底层开发实战
  17. r7 5800x配什么主板和显卡
  18. 人工智能期末考试复习(贲可荣 张彦铎)
  19. 第六章 go 文件操作
  20. openfire自带表结构

热门文章

  1. 三年经验java工资,含爱奇艺,小米,腾讯,阿里
  2. 从入门到精通!java可视化编程软件哪个好
  3. Java 微信公众号导出所有粉丝(openId)
  4. 关于自动布局更新约束方法的总结
  5. Win7/8出现An error occurred on the server when processing the URL解决办法
  6. Eclipse 构建Maven项目
  7. C#定义属性-静态属性
  8. Windows XP和Windows 7双系统安装和启动菜单修复
  9. 数据挖掘的相关知识例子
  10. 安装配置tengine