redux擴展工具_用鴨子擴展您的Redux App

redux擴展工具

How does your front-end application scale? How do you make sure that the code you’re writing is maintainable 6 months from now?

您的前端應用程序如何擴展? 您如何確定您正在編寫的代碼從現在起6個月內可維護?

Redux took the world of front-end development by storm in 2015 and established itself as a standard — even beyond the scope of React.

Redux在2015年席卷了前端開發領域,并確立了自己的標準-甚至超出了React的范圍。

At the company where I work, we recently finished refactoring a fairly large React codebase, adding redux instead of reflux.

在公司,我的工作,我們最近完成重構一個相當大的React的代碼庫,將終極版,而不是回流 。

We did it because moving forward would have been impossible without a well structured application and a good set of rules.

我們這樣做是因為沒有結構良好的應用程序和良好的規則,前進將是不可能的。

The codebase is more than two years old, and reflux was there from the beginning. We had to change code that wasn’t touched in more than a year and was pretty tangled with the React components.

該代碼庫已有兩年多的歷史了,從一開始就存在回流 。 我們不得不更改了一年多沒有碰到的代碼,并且與React組件糾纏不清。

Based on the work we did on the project, I put together this repo, explaining our approach in organizing our redux code.

基于我們在項目上所做的工作,我整理了此倉庫 ,解釋了組織redux代碼的方法。

When you learn about redux and the roles of actions and reducers, you start with very simple examples. Most tutorials available today don’t go to the next level. But if you’re building something with Redux that’s more complicated than a todo list, you’ll need a smarter way of scaling your codebase over time.

當您了解redux以及動作和reduce的角色時,您將從非常簡單的示例開始。 今天可用的大多數教程都不會再上一個臺階。 但是,如果您要使用Redux構建比待辦事項列表更復雜的東西,則需要一種更智能的方式來隨著時間擴展代碼庫。

Someone once said that naming things is one of the hardest jobs in computer science. I couldn’t agree more. But structuring folders and organizing files is a close second.

曾經有人說, 命名事物是計算機科學中最困難的工作之一。 我完全同意。 但是結構化文件夾和組織文件緊隨其后。

Let’s explore how we approached code organization in the past.

讓我們探討一下過去如何進行代碼組織。

功能與功能 (Function vs Feature)

There are two established approaches of structuring applications: function-first and feature-first.

有兩種建立應用程序結構的方法:“ 功能優先”和“ 功能優先”

One the left below you can see a function-first folder structure. On the right you can see a feature-first approach.

您可以在下面的左側看到功能優先的文件夾結構。 在右側,您可以看到功能優先的方法。

Function-first means that your top-level directories are named after the purpose of the files inside. So you have: containers, components, actions, reducers, etc.

“功能優先”意味著您的頂級目錄是根據內部文件的目的命名的。 因此,您擁有: 容器組件動作縮減器等等。

This doesn’t scale at all. As your app grows and you add more features, you add files into the same folders. So you end up with having to scroll inside a single folder to find your file.

這根本無法擴展。 隨著應用程序的增長和添加更多功能,您將文件添加到相同的文件夾中。 因此,您最終不得不在單個文件夾中滾動才能找到文件。

The problem is also about coupling the folders together. A single flow through your app will probably require files from all folders.

問題還在于將文件夾耦合在一起。 單次通過您的應用程序流可能需要所有文件夾中的文件。

One advantage of this approach is that it isolates — in our case — React from redux. So if you want to change the state management library, you know which folders you need to touch. If you change the view library, you can keep your redux folders intact.

這種方法的一個優勢是,在我們的案例中,它使React與Redux隔離開來。 因此,如果您想更改狀態管理庫,則知道需要觸摸哪些文件夾。 如果更改視圖庫,則可以保持redux文件夾完整。

Feature-first means that the top-level directories are named after the main features of the app: product, cart, session.

Feature-first意味著頂級目錄是根據應用程序的主要功能命名的: productcartsession

This approach scales much better, because each new feature comes with a new folder. But, you have no separation between the React components and redux. Changing one of them on the long run is a very tricky job.

這種方法的擴展性更好,因為每個新功能都帶有一個新文件夾。 但是,React組件和redux之間沒有分隔。 從長遠來看,更改其中之一是一項非常棘手的工作。

Additionally you have files that do not belong to any feature. You end up with a folder common or shared, because you want to reuse code across many features in your app.

此外,您有不屬于任何功能的文件。 由于要在應用程序中的許多功能之間重用代碼因此最終得到一個公用共享文件夾。

兩全其美 (The best of two worlds)

Although not in the scope of this article, I want to touch this single idea: always separate State Management files from UI files.

盡管不在本文討論范圍之內,但我還是想提出一個想法: 始終將狀態管理文件與UI文件分開。

Think about your application on the long run. Imagine what happens with the codebase when you switch from React to another library. Or think how your codebase would use ReactNative in parallel with the web version.

從長遠來看您的應用程序。 想象一下,當您從React切換到另一個庫時,代碼庫會發生什么。 或者考慮您的代碼庫如何將ReactNative與Web版本并行使用。

Our approach starts from the need to isolate the React code into a single folder — called views — and the redux code into a separate folder — called redux.

我們的方法首先需要將React代碼隔離到一個單獨的文件夾(稱為視圖)中,并將redux代碼隔離到一個單獨的文件夾中,稱為redux。

This first level split gives us the flexibility to organize the two separate parts of the app completely different.

第一級拆分使我們可以靈活地組織完全不同的應用程序的兩個獨立部分。

Inside the views folder, we prefer a function-first approach in structuring files. This feels very natural in the context of React: pages, layouts, components, enhancers etc.

在views文件夾中,我們更喜歡在結構化文件時采用功能優先的方法。 在React的上下文中,這感覺很自然: 頁面布局組件,增強器等。

To not go crazy with the number of files in a folder, we may have a feature based split inside each of these folders.

為了避免困擾一個文件夾中的文件數量,我們可能在每個文件夾中都有基于功能的拆分。

Then, inside the redux folder…

然后,在redux文件夾中…

輸入重新鴨子 (Enter re-ducks)

Each feature of the application should map to separate actions and reducers, so it makes sense to go for a feature-first approach.

應用程序的每個功能都應映射到單獨的操作和簡化程序,因此采用功能優先的方法是有意義的。

The original ducks modular approach is a nice simplification for redux and offers a structured way of adding each new feature in your app.

原始的ducks模塊化方法是redux的一個很好的簡化,并提供了一種結構化的方式來在您的應用程序中添加每個新功能。

Yet, we wanted to explore a bit what happens when the app scales. We realized that a single file for a feature becomes too cluttered and hard to maintain on the long run.

但是,我們想探索一下應用擴展時會發生什么。 我們意識到,功能的單個文件變得過于混亂,從長遠來看很難維護。

This is how re-ducks was born. The solution was to split each feature into a duck folder.

這就是再鴨的誕生 。 解決方案是將每個功能拆分到一個鴨子文件夾中。

duck/
├── actions.js
├── index.js
├── operations.js
├── reducers.js
├── selectors.js
├── tests.js
├── types.js
├── utils.js

A duck folder MUST:

鴨子文件夾必須:

  • contain the entire logic for handling only ONE concept in your app, ex: product, cart, session, etc.

    包含用于僅在您的應用中處理一個概念的完整邏輯,例如: productcartsession等。

  • have an index.js file that exports according to the original duck rules.

    有一個index.js文件,該文件根據原始的鴨子規則導出。

  • keep code with similar purpose in the same file, such as reducers, selectors, and actions

    將目的相似的代碼保存在同一文件中,例如reducersselectorsaction

  • contain the tests related to the duck.

    包含與鴨子有關的測試

For this example, we haven’t used any abstraction built on top of redux. When building software, it’s important to start with the least amount of abstractions. This way, you make sure that the cost of your abstractions doesn’t outweigh the benefits.

對于此示例,我們沒有使用基于redux構建的任何抽象。 在構建軟件時,從最少的抽象量開始很重要。 這樣,您可以確保抽象的成本不會超過收益。

If you need to convince yourself that abstractions can be bad, watch this awesome talk by Cheng Lou.

如果您需要使自己相信抽象可能是不好的,請觀看Cheng Lou的精彩演講 。

Let’s see what goes into each file.

讓我們看看每個文件中包含的內容。

種類 (Types)

The types file contains the names of the actions that you are dispatching in your application. As a good practice, you should try to scope the names based on the feature they belong to. This helps when debugging more complex applications.

類型文件包含要在應用程序中分派的動作的名稱。 作為一種好習慣,您應該嘗試根據名稱所屬的功能來確定名稱的范圍。 這有助于調試更復雜的應用程序。

const QUACK = "app/duck/QUACK";
const SWIM = "app/duck/SWIM";export default {QUACK,SWIM
};

動作 (Actions)

This file contains all the action creator functions.

該文件包含所有動作創建器功能。

import types from "./types";const quack = ( ) => ( {type: types.QUACK
} );const swim = ( distance ) => ( {type: types.SWIM,payload: {distance}
} );export default {swim,quack
};

Notice how all the actions are represented by functions, even if they are not parametrized. A consistent approach is more than needed in a large codebase.

請注意,即使未對參數進行參數設置,所有動作如何由函數表示。 在大型代碼庫中,一致的方法已遠遠超過了所需。

運作方式 (Operations)

To represent chained operations you need a redux middleware to enhance the dispatch function. Some popular examples are: redux-thunk, redux-saga or redux-observable.

為了表示鏈式操作,您需要一個Redux 中間件來增強調度功能。 一些流行的示例是: redux-thunk , redux-saga或redux-observable 。

In our case, we use redux-thunk. We want to separate the thunks from the action creators, even with the cost of writing extra code. So we define an operation as a wrapper over actions.

在我們的例子中,我們使用redux-thunk 。 我們希望將動作與動作創建者區分開來,即使付出編寫額外代碼的代價。 因此,我們將操作定義為動作的包裝。

If the operation only dispatches a single action — doesn’t actually use redux-thunk — we forward the action creator function. If the operation uses a thunk, it can dispatch many actions and chain them with promises.

如果該操作僅調度單個操作-實際上未使用redux-thunk-我們將轉發操作創建者函數。 如果操作使用重擊,則可以分派許多操作并將它們與承諾鏈接在一起。

import actions from "./actions";// This is a link to an action defined in actions.js.
const simpleQuack = actions.quack;// This is a thunk which dispatches multiple actions from actions.js
const complexQuack = ( distance ) => ( dispatch ) => {dispatch( actions.quack( ) ).then( ( ) => {dispatch( actions.swim( distance ) );dispatch( /* any action */ );} );
}export default {simpleQuack,complexQuack
};

Call them operations, thunks, sagas, epics, it’s your choice. Just find a naming convention and stick with it.

稱它們為操作,重擊,薩加斯,史詩,這是您的選擇。 只要找到一個命名約定并堅持下去即可。

At the end, when we discuss the index, we’ll see that the operations are part of the public interface of the duck. Actions are encapsulated, operations are exposed.

最后,當我們討論index時 ,我們將看到操作是Duck的公共接口的一部分。 動作被封裝,操作被公開。

減速器 (Reducers)

If a feature has more facets, you should definitely use multiple reducers to handle different parts of the state shape. Additionally, don’t be afraid to use combineReducers as much as needed. This gives you a lot of flexibility when working with a complex state shape.

如果特征具有更多的構面,則絕對應使用多個化簡器來處理狀態形狀的不同部分。 此外,不要害怕根據需要使用CombineReducers 。 在處理復雜的狀態形狀時,這為您提供了很大的靈活性。

import { combineReducers } from "redux";
import types from "./types";/* State Shape
{quacking: bool,distance: number
}
*/const quackReducer = ( state = false, action ) => {switch( action.type ) {case types.QUACK: return true;/* ... */default: return state;}
}const distanceReducer = ( state = 0, action ) => {switch( action.type ) {case types.SWIM: return state + action.payload.distance;/* ... */default: return state;}
}const reducer = combineReducers( {quacking: quackReducer,distance: distanceReducer
} );export default reducer;

In a large scale application, your state tree will be at least 3 level deep. Reducer functions should be as small as possible and handle only simple data constructs. The combineReducers utility function is all you need to build a flexible and maintainable state shape.

在大型應用程序中,您的狀態樹將至少深3層。 Reducer函數應盡可能小,并且僅處理簡單的數據構造。 CombineReducers實用程序功能是構建靈活且可維護的狀態形狀所需的全部。

Check out the complete example project and look how combineReducers is used. Once in the reducers.js files and then in the store.js file, where we put together the entire state tree.

查看完整的示例項目,并查看如何使用CombineReducers 。 一次進入reducers.js文件,然后進入store.js文件,在這里我們將整個狀態樹放在一起。

選擇器 (Selectors)

Together with the operations, the selectors are part of the public interface of a duck. The split between operations and selectors resembles the CQRS pattern.

選擇器與操作一起是鴨子公共接口的一部分。 操作和選擇器之間的劃分類似于CQRS模式 。

Selector functions take a slice of the application state and return some data based on that. They never introduce any changes to the application state.

選擇器函數獲取應用程序狀態的一部分,并根據該狀態返回一些數據。 他們從不對應用程序狀態進行任何更改。

function checkIfDuckIsInRange( duck ) {return duck.distance > 1000;
}export default {checkIfDuckIsInRange
};

指數 (Index)

This file specifies what gets exported from the duck folder. It will:

此文件指定從duck文件夾導出的內容。 它會:

  • export as default the reducer function of the duck.

    默認情況下導出鴨子的reduce功能。
  • export as named exports the selectors and the operations.

    導出為命名,導出選擇器和操作。
  • export the types if they are needed in other ducks.

    如果其他鴨子需要它們,則將其導出。
import reducer from "./reducers";export { default as duckSelectors } from "./selectors";
export { default as duckOperations } from "./operations";
export { default as duckTypes } from "./types";export default reducer;

測驗 (Tests)

A benefit of using Redux and the ducks structure is that you can write your tests next to the code you are testing.

使用Redux和ducks結構的好處是您可以在要測試的代碼旁邊編寫測試。

Testing your Redux code is fairly straight-forward:

測試您的Redux代碼非常簡單:

import expect from "expect.js";
import reducer from "./reducers";
import actions from "./actions";describe( "duck reducer", function( ) {describe( "quack", function( ) {const quack = actions.quack( );const initialState = false;const result = reducer( initialState, quack );it( "should quack", function( ) {expect( result ).to.be( true ) ;} );} );
} );

Inside this file you can write tests for reducers, operations, selectors, etc.

在此文件中,您可以編寫用于化簡,操作,選擇器等的測試。

I could write a whole different article about the benefits of testing your code, there are so many of them. Just do it!

我可以寫一篇關于測試代碼的好處的不同文章,其中有很多。 去做就對了!

就是這樣 (So there it is)

The nice part about re-ducks is that you get to use the same pattern for all your redux code.

關于重新鴨子的好處是,您可以對所有redux代碼使用相同的模式。

The feature-based split for the redux code is much more flexible and scalable as your application codebase grows. And the function-based split for views works when you build small components that are shared across the application.

隨著您的應用程序代碼庫的增長,redux代碼的基于功能的拆分更加靈活和可擴展。 當您構建在應用程序之間共享的小型組件時,基于視圖的基于功能的拆分將起作用。

You can check out a full react-redux-example codebase here. Just keep in mind that the repo is still under active development.

您可以在此處查看完整的react-redux-example代碼庫。 請記住,回購仍在積極開發中。

How do you structure your redux apps? I’m looking forward to hearing some feedback on this approach I’ve presented.

您如何構造您的redux應用程序? 我期待聽到有關我提出的這種方法的一些反饋。

If you found this article useful, click on the green heart below and I will know my efforts are not in vain.

如果您發現本文有用,請單擊下面的綠色心臟,我將知道我的努力沒有白費。

翻譯自: https://www.freecodecamp.org/news/scaling-your-redux-app-with-ducks-6115955638be/

redux擴展工具

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

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

相關文章

mac下源碼安裝redis

轉載:http://www.jianshu.com/p/6b5eca8d908b 下載安裝包 redis-3.0.7.tar.gz 官網地址:http://redis.io/download 解壓:tar -zvxf redis-3.0.7.tar.gz 將解壓后的文件夾放到 /usr/local目錄下 編譯測試:接下來在終端中切換到/usr/local/red…

代碼掃描工具測試覆蓋率工具

測試覆蓋率工具轉載于:https://www.cnblogs.com/vivian-test/p/5398289.html

php splqueue 5.5安裝,解析PHP標準庫SPL數據結構

SPL提供了雙向鏈表、堆棧、隊列、堆、降序堆、升序堆、優先級隊列、定長數組、對象容器SplQueue 隊列類進出異端&#xff0c;先進先出<?php $obj new SplQueue();//插入一個節點到top位置$obj->enqueue(1);$obj->enqueue(2);$obj->enqueue(3);/**SplQueue Object…

Beta階段敏捷沖刺總結

設想和目標 1. 我們的軟件要解決什么問題&#xff1f;是否定義得很清楚&#xff1f;是否對典型用戶和典型場景有清晰的描述&#xff1f; 在最開始的時候我們就是為了解決集美大學計算機工程學院網頁沒有搜索引擎的問題。因為沒有搜索引擎&#xff0c;在搜索內容時需要根據查找信…

c語言 二進制壓縮算法_使用C ++解釋的二進制搜索算法

c語言 二進制壓縮算法by Pablo E. Cortez由Pablo E.Cortez 使用C 解釋的二進制搜索算法 (Binary Search Algorithms Explained using C) Binary search is one of those algorithms that you’ll come across on every (good) introductory computer science class. It’s an …

【LATEX】個人版latex論文模板

以下是我的個人論文模板&#xff0c;運行環境為Xelatex(在線ide&#xff1a;Sharelatex.com) 鑒于本人常有插入程序的需求&#xff0c;故引用了lstlisting \RequirePackage{ifxetex} \ifxetex\documentclass[hyperref, UTF8, c5size, no-math, winfonts&#xff0c;a4paper]{ct…

初識virtual memory

一、先談幾個重要的東西 virtual memory是一個抽象概念&#xff0c;書上的原文是"an abstraction of main memory known as virtual memory"&#xff08;參考資料p776&#xff09;。那么什么是抽象概念。下面說說我個人對這個東西的理解。 所謂抽象概念是指抽象出來的…

java創建mysql驅動,JDBC之Java連接mysql實現增刪改查

使用軟件&#xff1a;mysql、eclipse鏈接步驟&#xff1a;1.注冊驅動2.創建一個連接對象3.寫sql語句4.執行sql語句并返回一個結果或者結果集5.關閉鏈接(一般就是connection、statement、setresult)這三個連接對象&#xff0c;關閉順序一般是(setresult ---> statement …

算法第五章作業

1.你對回溯算法的理解&#xff08;2分&#xff09; 回溯法&#xff08;探索與回溯法&#xff09;是一種選優搜索法&#xff0c;又稱為試探法&#xff0c;按選優條件向前搜索&#xff0c;以達到目標。但當探索到某一步時&#xff0c;發現原先選擇并不優或達不到目標&#xff0c;…

c++編碼風格指南_100%正確的編碼樣式指南

c編碼風格指南Here are three links worth your time:這是三個值得您花費時間的鏈接&#xff1a; The 100% correct coding style guide (4 minute read) 100&#xff05;正確的編碼樣式指南( 閱讀4分鐘 ) I wrote a programming language. Here’s how you can, too (10 minu…

xp開機黑屏故障分析

今天裝完xp系統之后&#xff0c;重啟開機發現竟然黑屏了&#xff0c;查資料發現有很多用戶在修改分辨率后&#xff0c;因顯示器不支持修改后的分辨率&#xff0c;會出現電腦黑屏的情況。分辨率調高了&#xff0c;超出了屏幕的范圍&#xff0c;肯定會黑屏&#xff0c;而且這個問…

應用程序圖標_如何制作完美的應用程序圖標

應用程序圖標by Nabeena Mali通過Nabeena Mali 如何制作完美的應用程序圖標 (How to Make the Perfect App Icon) With just 24 app icon slots on the first page of an iPhone home screen, or 28 if you have a fancy iPhone 7, creating the perfect app icon is a vital …

Luogu3702 SDOI2017 序列計數 矩陣DP

傳送門 不考慮質數的條件&#xff0c;可以考慮到一個很明顯的$DP:$設$f_{i,j}$表示選$i$個數&#xff0c;和$mod\ pj$的方案數&#xff0c;顯然是可以矩陣優化$DP$的。 而且轉移矩陣是循環矩陣&#xff0c;所以可以只用第一行的數字代替整個矩陣。當然了這道題$p \leq 100$矩陣…

java閏年的年份,Java案例-判斷給定年份是閏年

專注學子高考志愿填報&#xff0c;分享你所不知道信息。Java案例-判斷給定年份是閏年案例描述編寫程序&#xff0c;判斷給定的某個年份是否是閏年。閏年的判斷規則如下&#xff1a;(1)若某個年份能被4整除但不能被100整除&#xff0c;則是閏年。(2)若某個年份能被400整除&#…

通過path繪制點擊區域

通過path繪制點擊區域 效果 源碼 https://github.com/YouXianMing/Animations // // TapDrawImageView.h // TapDrawImageView // // Created by YouXianMing on 16/5/9. // Copyright © 2016年 YouXianMing. All rights reserved. //#import <UIKit/UIKit.h> #…

Raft與MongoDB復制集協議比較

在一文搞懂raft算法一文中&#xff0c;從raft論文出發&#xff0c;詳細介紹了raft的工作流程以及對特殊情況的處理。但算法、協議這種偏抽象的東西&#xff0c;僅僅看論文還是比較難以掌握的&#xff0c;需要看看在工業界的具體實現。本文關注MongoDB是如何在復制集中使用raft協…

db2 前滾會話

前滾會話 - CLP 示例ROLLFORWARD DATABASE 命令允許每次指定多個操作&#xff0c;各個操作由關鍵字 AND 隔開。例如&#xff0c;要前滾至日志末尾&#xff0c;然后完成&#xff0c;可將下列獨立的命令&#xff1a;db2 rollforward db sample to end of logsdb2 rollforward db …

史上最爛代碼_歷史上最大的代碼庫

史上最爛代碼Here’s a diagram of the biggest codebases in history, as measured by lines of code:這是歷史上最大的代碼庫的圖表&#xff0c;以代碼行來衡量&#xff1a; As you can see, Google has by far the largest codebase of all. And all 2 billion lines of co…

php添加jpeg,PHP-如何將JPEG圖像保存為漸進JPEG?

我具有以下將JPEG保存為漸進JPEG的功能.它已保存,但不是漸進式JPEG.這個對嗎 &#xff1f;function save($filename, $image_type IMAGETYPE_JPEG, $compression 75, $permissions null) {if ($image_type IMAGETYPE_JPEG) {imageinterlace($this->image, true); //conv…

Mysql添加字段.md

alter table td_user add gender bit DEFAULT 0 COMMENT 性別; 轉載于:https://www.cnblogs.com/bihanghang/p/10167446.html