redux ngrx_另一個減少Redux(NGRX)應用程序樣板的指南

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392623.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392623.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392623.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode 242. 有效的字母異位詞

給定兩個字符串 s 和 t ,編寫一個函數來判斷 t 是否是 s 的字母異位詞。 示例 1: 輸入: s “anagram”, t “nagaram” 輸出: true 示例 2: 輸入: s “rat”, t “car” 輸出: false 代碼 class Solution {public boolean isAnagram(String s, String t) {…

技巧:使用User Control做HTML生成

User Control大家肯定不會陌生,在使用ASP.NET的過程中,除了aspx頁面,最常見的就莫過于ascx了。ascx是一個有獨立邏輯的組件,提供了強大的復用特性,合理使用,能夠大大提高開發效率。通過User Control直接生成…

Spring Boot干貨系列:(二)配置文件解析

前言 上一篇介紹了Spring Boot的入門,知道了Spring Boot使用“習慣優于配置”(項目中存在大量的配置,此外還內置了一個習慣性的配置,讓你無需手動進行配置)的理念讓你的項目快速運行起來。所以,我們要想把S…

mysql常用操作記錄

(1)判斷表中一個字段是空,可為:字段名 IS NULL(2)類似oracle的decode作用:IF(字段名>0,字段名,0)(3)時間格式(年-月-日):DATE_FORM…

小愛音響調用php接口_阿里API調用二(PHP)

接口地址拼合成功后,用curl函數post獲取阿里返回的完整數據,將地址傳入getContent()方法中,絕對能獲取用戶數據。public function getContent($url){$ch curl_init();// 初始化curl_setopt($ch,CURLOPT_URL,$apiprourlall);curl_setopt($ch,…

leetcode 452. 用最少數量的箭引爆氣球(貪心算法)

在二維空間中有許多球形的氣球。對于每個氣球,提供的輸入是水平方向上,氣球直徑的開始和結束坐標。由于它是水平的,所以縱坐標并不重要,因此只要知道開始和結束的橫坐標就足夠了。開始坐標總是小于結束坐標。 一支弓箭可以沿著 x…

javascript編程題_如何開始使用JavaScript進行競爭性編程

javascript編程題by Priyabrata Biswas通過Priyabrata Biswas 如何開始使用JavaScript進行競爭性編程 (How to get started with Competitive Programming in JavaScript) If you’re not familiar with competitive programming, basically it is a mind sport with the aim …

hibernate Criteria(條件查詢接口)

Criteria&#xff08;條件查詢接口&#xff09; // 1.簡單查詢 List<Customer> list session.createCriteria(Customer.class).list();// 2.條件查詢: Criteria criteria session.createCriteria(Customer.class); criteria.add(Restrictions.eq("name",&quo…

ElastciSearch簡單總結(筆記)

前言&#xff1a; 前段時間在項目中使用了es,作為一個當前比較流行的分布式搜索引擎&#xff0c;在學習和使用它的過程中&#xff0c;踩了不少坑&#xff0c;這篇文章先簡單整理了一下&#xff0c;后續會整理一下之前踩過的一些坑。 1. ElastciSearch是什么 ElasticSearch是一…

記一次ArrayList產生的線上OOM問題

前言&#xff1a;本以為(OutOfMemoryError)OOM問題會離我們很遠&#xff0c;但在一次生產上線灰度的過程中就出現了Java.Lang.OutOfMemoryError:Java heap space異常&#xff0c;通過對線上日志的查看&#xff0c;最終定位到ArrayList#addAll方法中&#xff0c;出現這個問題的原…

leetcode 222. 完全二叉樹的節點個數(dfs)

給出一個完全二叉樹&#xff0c;求出該樹的節點個數。說明&#xff1a;完全二叉樹的定義如下&#xff1a;在完全二叉樹中&#xff0c;除了最底層節點可能沒填滿外&#xff0c;其余每層節點數都達到最大值&#xff0c;并且最下面一層的節點都集中在該層最左邊的若干位置。若最底…

css 計算屬性的應用_如何使用一點CSS Grid魔術設計計算器應用

css 計算屬性的應用by Deepika Gunda由Deepika Gunda 如何使用一點CSS Grid魔術設計計算器應用 (How to use a little CSS Grid magic to design a calculator app) This article is a quick intro to CSS Grid. We will be making a calculator using it.本文是CSS Grid的快速…

vc調試大全

一、調試基礎 調試快捷鍵 F5&#xff1a; 開始調試 ShiftF5: 停止調試 F10&#xff1a; 調試到下一句&#xff0c;這里是單步跟蹤 F11&#xff1a; 調試到下一句&#xff0c;跟進函數內部 ShiftF11: 從當前函數中跳出 CtrlF10: 調試到光標所在位置 F9&#xff1a; …

Google-Guava-EventBus源碼解讀

Guava是Google開源的一個Java基礎類庫&#xff0c;它在Google內部被廣泛使用。Guava提供了很多功能模塊比如&#xff1a;集合、并發庫、緩存等&#xff0c;EventBus是其中的一個module&#xff0c;本篇結合EventBus源碼來談談它的設計與實現。 概要 首先&#xff0c;我們先來預…

leetcode 1370. 上升下降字符串

給你一個字符串 s &#xff0c;請你根據下面的算法重新構造字符串&#xff1a; 從 s 中選出 最小 的字符&#xff0c;將它 接在 結果字符串的后面。 從 s 剩余字符中選出 最小 的字符&#xff0c;且該字符比上一個添加的字符大&#xff0c;將它 接在 結果字符串后面。 重復步驟…

mysql 設置事物自動提交_mysql事務自動提交的問題

1&#xff1a;mysql的aut0commit配置默認是開啟的&#xff0c;也就是沒執行一條sql都會提交一次&#xff0c;就算顯示的開啟事務也會導致多條SQL不在一個事務中&#xff0c;如果需要相關的SQL在同一個事務中執行&#xff0c;那么必須將autocommit設置為OFF&#xff0c;再顯式開…

rest laravel_如何通過測試驅動開發來構建Laravel REST API

rest laravelby Kofo Okesola由Kofo Okesola 如何通過測試驅動開發來構建Laravel REST API (How to build a Laravel REST API with Test-Driven Development) There is a famous quote by James Grenning, one of the pioneers in TDD and Agile development methodologies:T…

python之numpy

numpy是一個多維的數組對象&#xff0c;類似python的列表&#xff0c;但是數組對象的每個元素之間由空格隔開。 一、數組的創建 1.通過numpy的array(參數)&#xff0c;參數可以是列表、元組、數組、生成器等 由arr2和arr3看出&#xff0c;對于多維數組來說&#xff0c;如果最里…

git 上傳

轉載于:https://www.cnblogs.com/benbentu/p/6543154.html

Liferay 部署war包時候的deployDirectory 細節分析

引入&#xff1a; 在上文中&#xff0c;我們從宏觀上講解了Liferay部署war包的動作是如何觸發監聽器并且完成部署過程的&#xff0c;但是其中最核心的一塊deployDirectory我們沒講&#xff0c;它的作用是當有了臨時目錄并且已經把war包的內容展開到該目錄之后&#xff0c;是如何…