Redux API之applyMiddleware

applyMiddleware(...middlewares)

使用包含自定義功能的 middleware 來擴展 Redux 是一種推薦的方式。Middleware 可以讓你包裝 store 的dispatch?方法來達到你想要的目的。同時, middleware 還擁有“可組合”這一關鍵特性。多個 middleware 可以被組合到一起使用,形成 middleware 鏈。其中,每個 middleware 都不需要關心鏈中它前后的 middleware 的任何信息。

Middleware 最常見的使用場景是無需引用大量代碼或依賴類似?Rx?的第三方庫實現異步 actions。這種方式可以讓你像 dispatch 一般的 actions 那樣 dispatch?異步 actions。

例如,redux-thunk?支持 dispatch function,以此讓 action creator 控制反轉。被 dispatch 的 function 會接收?dispatch?作為參數,并且可以異步調用它。這類的 function 就稱為?thunk。另一個 middleware 的示例是?redux-promise。它支持 dispatch 一個異步的?Promise?action,并且在 Promise resolve 后可以 dispatch 一個普通的 action。

Middleware 并不需要和?createStore?綁在一起使用,也不是 Redux 架構的基礎組成部分,但它帶來的益處讓我們認為有必要在 Redux 核心中包含對它的支持。因此,雖然不同的 middleware 可能在易用性和用法上有所不同,它仍被作為擴展?dispatch?的唯一標準的方式。

參數

  • ...middlewares?(arguments): 遵循 Redux?middleware API?的函數。每個 middleware 接受?Store?的dispatch?和?getState?函數作為命名參數,并返回一個函數。該函數會被傳入 被稱為?next?的下一個 middleware 的 dispatch 方法,并返回一個接收 action 的新函數,這個函數可以直接調用next(action),或者在其他需要的時刻調用,甚至根本不去調用它。調用鏈中最后一個 middleware 會接受真實的 store 的?dispatch?方法作為?next?參數,并借此結束調用鏈。所以,middleware 的函數簽名是?({?getState,?dispatch?})?=>?next?=>?action

返回值

(Function) 一個應用了 middleware 后的 store enhancer。這個 store enhancer 就是一個函數,并且需要應用到?createStore。它會返回一個應用了 middleware 的新的?createStore

示例: 自定義 Logger Middleware

 1 import { createStore, applyMiddleware } from 'redux'
 2 import todos from './reducers'
 3 
 4 function logger({ getState }) {
 5   return (next) => (action) => {
 6     console.log('will dispatch', action)
 7 
 8     // 調用 middleware 鏈中下一個 middleware 的 dispatch。
 9     let returnValue = next(action)
10 
11     console.log('state after dispatch', getState())
12 
13     // 一般會是 action 本身,除非
14     // 后面的 middleware 修改了它。
15     return returnValue
16   }
17 }
18 
19 let createStoreWithMiddleware = applyMiddleware(logger)(createStore)
20 let store = createStoreWithMiddleware(todos, [ 'Use Redux' ])
21 
22 store.dispatch({
23   type: 'ADD_TODO',
24   text: 'Understand the middleware'
25 })
26 // (將打印如下信息:)
27 // will dispatch: { type: 'ADD_TODO', text: 'Understand the middleware' }
28 // state after dispatch: [ 'Use Redux', 'Understand the middleware' ]
View Code

示例: 使用 Thunk Middleware 來做異步 Action

  1 import { createStore, combineReducers, applyMiddleware } from 'redux'
  2 import thunk from 'redux-thunk'
  3 import * as reducers from './reducers'
  4 
  5 // 調用 applyMiddleware,使用 middleware 增強 createStore:
  6 let createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
  7 
  8 // 像原生 createStore 一樣使用。
  9 let reducer = combineReducers(reducers)
 10 let store = createStoreWithMiddleware(reducer)
 11 
 12 function fetchSecretSauce() {
 13   return fetch('https://www.google.com/search?q=secret+sauce')
 14 }
 15 
 16 // 這些是你已熟悉的普通 action creator。
 17 // 它們返回的 action 不需要任何 middleware 就能被 dispatch。
 18 // 但是,他們只表達「事實」,并不表達「異步數據流」
 19 
 20 function makeASandwich(forPerson, secretSauce) {
 21   return {
 22     type: 'MAKE_SANDWICH',
 23     forPerson,
 24     secretSauce
 25   }
 26 }
 27 
 28 function apologize(fromPerson, toPerson, error) {
 29   return {
 30     type: 'APOLOGIZE',
 31     fromPerson,
 32     toPerson,
 33     error
 34   }
 35 }
 36 
 37 function withdrawMoney(amount) {
 38   return {
 39     type: 'WITHDRAW',
 40     amount
 41   }
 42 }
 43 
 44 // 即使不使用 middleware,你也可以 dispatch action:
 45 store.dispatch(withdrawMoney(100))
 46 
 47 // 但是怎樣處理異步 action 呢,
 48 // 比如 API 調用,或者是路由跳轉?
 49 
 50 // 來看一下 thunk。
 51 // Thunk 就是一個返回函數的函數。
 52 // 下面就是一個 thunk。
 53 
 54 function makeASandwichWithSecretSauce(forPerson) {
 55 
 56   // 控制反轉!
 57   // 返回一個接收 `dispatch` 的函數。
 58   // Thunk middleware 知道如何把異步的 thunk action 轉為普通 action。
 59 
 60   return function (dispatch) {
 61     return fetchSecretSauce().then(
 62       sauce => dispatch(makeASandwich(forPerson, sauce)),
 63       error => dispatch(apologize('The Sandwich Shop', forPerson, error))
 64     )
 65   }
 66 }
 67 
 68 // Thunk middleware 可以讓我們像 dispatch 普通 action
 69 // 一樣 dispatch 異步的 thunk action。
 70 
 71 store.dispatch(
 72   makeASandwichWithSecretSauce('Me')
 73 )
 74 
 75 // 它甚至負責回傳 thunk 被 dispatch 后返回的值,
 76 // 所以可以繼續串連 Promise,調用它的 .then() 方法。
 77 
 78 store.dispatch(
 79   makeASandwichWithSecretSauce('My wife')
 80 ).then(() => {
 81   console.log('Done!')
 82 })
 83 
 84 // 實際上,可以寫一個 dispatch 其它 action creator 里
 85 // 普通 action 和異步 action 的 action creator,
 86 // 而且可以使用 Promise 來控制數據流。
 87 
 88 function makeSandwichesForEverybody() {
 89   return function (dispatch, getState) {
 90     if (!getState().sandwiches.isShopOpen) {
 91 
 92       // 返回 Promise 并不是必須的,但這是一個很好的約定,
 93       // 為了讓調用者能夠在異步的 dispatch 結果上直接調用 .then() 方法。
 94 
 95       return Promise.resolve()
 96     }
 97 
 98     // 可以 dispatch 普通 action 對象和其它 thunk,
 99     // 這樣我們就可以在一個數據流中組合多個異步 action。
100 
101     return dispatch(
102       makeASandwichWithSecretSauce('My Grandma')
103     ).then(() =>
104       Promise.all([
105         dispatch(makeASandwichWithSecretSauce('Me')),
106         dispatch(makeASandwichWithSecretSauce('My wife'))
107       ])
108     ).then(() =>
109       dispatch(makeASandwichWithSecretSauce('Our kids'))
110     ).then(() =>
111       dispatch(getState().myMoney > 42 ?
112         withdrawMoney(42) :
113         apologize('Me', 'The Sandwich Shop')
114       )
115     )
116   }
117 }
118 
119 // 這在服務端渲染時很有用,因為我可以等到數據
120 // 準備好后,同步的渲染應用。
121 
122 import { renderToString } from 'react-dom/server'
123 
124 store.dispatch(
125   makeSandwichesForEverybody()
126 ).then(() =>
127   response.send(renderToString(<MyApp store={store} />))
128 )
129 
130 // 也可以在任何導致組件的 props 變化的時刻
131 // dispatch 一個異步 thunk action。
132 
133 import { connect } from 'react-redux'
134 import { Component } from 'react'
135 
136 class SandwichShop extends Component {
137   componentDidMount() {
138     this.props.dispatch(
139       makeASandwichWithSecretSauce(this.props.forPerson)
140     )
141   }
142 
143   componentWillReceiveProps(nextProps) {
144     if (nextProps.forPerson !== this.props.forPerson) {
145       this.props.dispatch(
146         makeASandwichWithSecretSauce(nextProps.forPerson)
147       )
148     }
149   }
150 
151   render() {
152     return <p>{this.props.sandwiches.join('mustard')}</p>
153   }
154 }
155 
156 export default connect(
157   state => ({
158     sandwiches: state.sandwiches
159   })
160 )(SandwichShop)
View Code

小貼士

  • Middleware 只是包裝了 store 的?dispatch?方法。技術上講,任何 middleware 能做的事情,都可能通過手動包裝?dispatch?調用來實現,但是放在同一個地方統一管理會使整個項目的擴展變的容易得多。

  • 如果除了?applyMiddleware,你還用了其它 store enhancer,一定要把?applyMiddleware?放到組合鏈的前面,因為 middleware 可能會包含異步操作。比如,它應該在?redux-devtools?前面,否則 DevTools 就看不到 Promise middleware 里 dispatch 的 action 了。

  • 如果你想有條件地使用 middleware,記住只 import 需要的部分:

?

1 let middleware = [ a, b ]
2 if (process.env.NODE_ENV !== 'production') {
3   let c = require('some-debug-middleware')
4   let d = require('another-debug-middleware')
5   middleware = [ ...middleware, c, d ]
6 }
7 const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore)
View Code
  • 這樣做有利于打包時去掉不需要的模塊,減小打包文件大小。

  • 有想過?applyMiddleware?本質是什么嗎?它肯定是比 middleware 還強大的擴展機制。實際上,applyMiddleware?只是被稱為 Redux 最強大的擴展機制的?store enhancers?中的一個范例而已。你不太可能需要實現自己的 store enhancer。另一個 store enhancer 示例是?redux-devtools。Middleware 并沒有 store enhancer 強大,但開發起來卻是更容易的。

  • Middleware 聽起來比實際難一些。真正理解 middleware 的唯一辦法是了解現有的 middleware 是如何工作的,并嘗試自己實現。需要的功能可能錯綜復雜,但是你會發現大部分 middleware 實際上很小,只有 10 行左右,是通過對它們的組合使用來達到最終的目的。

?

轉載于:https://www.cnblogs.com/ZSG-DoBestMe/p/5280171.html

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

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

相關文章

計算機2018創業方向,推薦2018年創業的方向

原標題&#xff1a;推薦2018年創業的方向1 新電商傳統的零售業收到互聯網電商的重沖擊&#xff0c;從而進行線上線下的結合是必然的趨勢&#xff0c;新零售&#xff0c;新電商&#xff0c;是幾千萬零售企業成功轉型的必然之路&#xff0c;學習一套全面的新電商轉型的方法&#…

包無法安裝_詳細教程 | 安裝Python編程環境以及使用OpenpyXl操作Excel

詳細教程 | 安裝Python編程環境以及使用OpenpyXl操作Excel注意&#xff1a;下列教程為 Windows7 64位&#xff1b;Windows 10有部分步驟有差異&#xff0c;請參考使用&#xff01;01 下載Python程序安裝包首先前往Python官網 www.python.org,進入官網點擊 Downloads,然后點擊 W…

Activity、Fragment、Dialog基類簡單整理

版權聲明&#xff1a;本文為HaiyuKing原創文章&#xff0c;轉載請注明出處&#xff01; 概述 這里簡單記錄下Activity、Fragment、Dialog基類中的常規寫法&#xff0c;后續根據項目需求進行相應的擴展。 BaseActivity.java package com.why.project.myapptemplet.activity;impo…

request重定向_golang不想http自動處理重定向的解決方案

前言有時候發送http請求不想讓庫自動幫忙處理重定向&#xff0c;庫里面默認的是會把所有重定向都完成一遍&#xff0c;結果就是最后一個沒有重定向的請求的結果。因此需要一種方案直接獲取首次訪問的結果&#xff0c;不走重定向。go的http庫里面是使用如下代碼檢查重定向的&…

C語言項目開發-項目架構和編程命名規范

一個項目的流程&#xff1a;1、公司市場人員與客戶交流&#xff0c;了解客戶、引導客戶使用公司最優資源并產出一份市場需求文檔 2、公司需求人員&#xff08;BA&#xff09;與客戶交流&#xff0c;了解客戶需求并產出一個軟件需求文檔 3、項目經理、開發小組成員、需求人員&am…

ajax登錄驗證的原理,ajax用戶登錄驗證-get和post提交方式,與工作原理—2018-8-15...

ajax用戶登錄驗證&#xff1a;實例html>Ajax實戰:表單驗證用戶登錄郵箱: 密碼: 提交let btn document.getElementsByTagName(button)[0];btn.onclick function () {//1.創建xhr對象let xhr new XMLHttpRequest();//2.監聽響應狀態xhr.onreadystatechange function(){// …

將Python腳本打包成可執行文件

Python是一個腳本語言&#xff0c;被解釋器解釋執行。它的發布方式&#xff1a; .py文件&#xff1a;對于開源項目或者源碼沒那么重要的&#xff0c;直接提供源碼&#xff0c;需要使用者自行安裝Python并且安裝依賴的各種庫。&#xff08;Python官方的各種安裝包就是這樣做的&a…

float foo=42e1為什么錯_為什么重寫了equals()也要重寫hashCode()

小Hub領讀&#xff1a;雖然是很基礎的一篇文章&#xff0c;但是對于equals、hashcode兩個方法&#xff0c;相信很多人都與其中的規則不熟悉&#xff0c;來跟著小Hub花個8分鐘回顧一下&#xff01;作者&#xff1a;不學無數的程序員https://my.oschina.net/u/4030990/blog/31341…

ssh客戶端_一款基于TAS框架的SSH客戶端蠕蟲

TEA是一款基于TAS框架的SSH客戶端蠕蟲&#xff0c;從本質上說&#xff0c;它是一個仿冒的SSH客戶端&#xff0c;它能夠修改tty輸入/輸出來實現任意命令執行&#xff0c;或通過SSH連接來上傳自身以實現滲透感染。為了實現該工具的正常功能&#xff0c;遠程主機需要滿足以下條件&…

Selenium入門11 滾動條控制(通過js)

這一節要有js基礎。做web端的UI自動化必須要有html&#xff0c;css&#xff0c;javascript前端基礎。 滾動條控制&#xff1a; 1 移動垂直滾動條 document.documentElement.scrollTop 2 移動垂直滾動條 document.documentElement.scrollLeft 3 找到某個元素&#xff0c;移動到可…

Qt之QNetworkInterface

簡述 QNetworkInterface類負責提供主機的IP地址和網絡接口的列表。 QNetworkInterface表示了當前程序正在運行時與主機綁定的一個網絡接口。每個網絡接口可能包含0個或多個IP地址&#xff0c;每個IP地址都可選擇性地與一個子網掩碼和/或一個廣播地址相關聯。這樣的列表可以通過…

第二周計劃

上周計劃回顧 3.5 ~ 3.11 數據&#xff1a; 評師網爬取&#xff0c;完成&#xff1a;2k條記錄 finished后端 數據結構 技術選型 學校API封裝未完成&#xff1a;后端負責人出差 工作暫停產品 功能設計&#xff1a;主要功能提交&#xff1a;原型圖 幾個頁面 每個頁面大概功能完成…

python編程軟件排行榜_PYPL 9月編程語言排行榜發布 Python一枝獨秀

開發者可以將 PYPL 作為一個參考&#xff0c;決定學習何種語言或 IDE&#xff0c;或者在新的軟件項目中使用何種語言或數據庫。9 月份的榜單如下&#xff1a;前五名分別是 Python、Java、JavaScript、C# 與 PHP。相比去年 9 月份的數據&#xff0c;除了 Python 大幅上漲了 4.5%…

分享到系統面板_win7電腦沒有nvidia控制面板怎么辦【解決方法】

我們在使用電腦的時候&#xff0c;當電腦顯卡出現問題導致屏幕畫面不清晰時&#xff0c;可以使用win7系統自帶nvidia控制面板&#xff0c;它能夠對顯卡進行設置&#xff0c;提升顯卡功能&#xff0c;不過很多電腦用戶點擊nvidia控制面板時卻提示nvidia顯示設置不可用&#xff0…

Python之數據加密與解密(hashlib、hmac、random、base64、pycrypto)--轉載

本文內容 數據加密概述Python中實現數據加密的模塊簡介hashlib與hmac模塊介紹random與secrets模塊介紹base64模塊介紹pycrypto模塊介紹總結參考文檔提示&#xff1a; Python 2.7中的str是字節串&#xff0c;而Python 3.x中的str是字符串。本文中的代碼都是通過Python 2.7實現的…

day3-文件操作之基本操作

一、文件的基本操作 文件內容&#xff1a; Somehow, it seems the love I knew was always the most destructive kind 不知為何&#xff0c;我經歷的愛情總是最具毀滅性的的那種 Yesterday when I was young 昨日當我年少輕狂1、read() 當read()函數中傳入整數(int)參數&#…

QT連接多種數據庫f方法及測試

QT提供了對多種數據庫的訪問支持&#xff0c;對SQL Server也可以通過ODBC來進行訪問。要想順利訪問SQL Server。 首先要保證以下幾點&#xff1a;1. QT編譯時已經編譯了QtSql2. 編譯了ODBC插件。可以通過 configure -plugin-sql-odbc來保證&#xff0c;也可以單獨編譯~/src/plu…

服務器如何實現電腦無線橋接,無線路由器WDS橋接成功副路由器下電腦無法上網怎么辦【解決方法】...

摘 要無線WDS橋接設置完成后&#xff0c;在副路由器管理面&#xff0c;運行狀態 無線狀態 中&#xff0c;WDS狀態顯示成功&#xff0c;但電腦通過副路由無法上網。該問題可能與主、副路由器的設置有關&#xff0c;如下圖所示&#xff1a; 解決辦法&#xff1a; 排查一&#xff…

spad 探測器_從光到光子—“單光子”探測器

光電探測器光電探測器是指在光輻射作用下將其非傳導電荷變為傳導電荷的一類器件。在電子學中&#xff0c;二極管是一種具有不對稱傳輸特性的雙端電子元件&#xff0c;在一個方向上對電流具有低(理想為零)電阻&#xff0c;在另一個方向上具有高(理想為無限)電阻。最常見的類型如…

天地圖專題五:在天地圖上繪制電子區域并保存數據

版權聲明&#xff1a;本文為博主原創文章&#xff0c;轉載請注明出處。 上一文章講了如何在天地圖上顯示坐標軌跡。 本文介紹如何在天地圖上繪制電子區域&#xff08;電子范圍或電子柵欄&#xff09;&#xff0c;并且&#xff0c;我們要將我們繪制的電子區域的坐標數據保存到數…