摘要:本文轉載自眾成翻譯譯者鏈接原文今天,我們在方法中使用中間件來管理我們的代碼中的復雜狀態變化。中間件是一個很好的地方。我們中間件我們將實現一些中間件它將代表我們處理異步請求。中間件位于動作和歸并器之間。讓我們創建我們的第一個中間件。
本文轉載自:眾成翻譯
譯者:iOSDevLog
鏈接:http://www.zcfy.cc/article/3810
原文:https://www.fullstackreact.com/30-days-of-react/day-21/
今天,我們在Redux方法中使用Redux中間件來管理我們的代碼中的復雜狀態變化。
昨天, 我們連接的點與Redux, 從工作通過歸并器, 更新行動的創造者, 并連接Redux到React組件。 Redux中間件 將解鎖更多的權力, 我們今天將會觸及。
Redux中間件中間件通常指的是軟件服務, "粘合在一起" 在現有軟件中的獨立功能。對于Redux, 中間件提供了一個 第三方擴展點, 在分發動作和將分發交給歸并器之間:
[ Action ] [ Middleware ] [ Dispatcher ]
[ 動作 ] [ 中間件 ] [ 分發 ]
中間件的示例包括日志記錄、崩潰報告、路由、處理異步請求等。
讓我們來處理異步請求, 就像對服務器的 HTTP 調用那樣。中間件是一個很好的地方。
我們中間件api我們將實現一些中間件, 它將代表我們處理異步請求。
中間件位于動作和歸并器之間。它可以監聽所有的調度和執行代碼與行動和當前狀態的細節。中間件提供了一個強大的抽象。讓我們來看看如何使用它來管理我們自己的。
繼續我們從昨天開始的currentTime Redux的工作, 讓我們構建我們的中間件, 以獲取當前的時間從服務器, 我們用幾天前寫的真實從 API 服務獲取時間。
在我們做得太多之前, 讓我們從reducers.js 文件的rootReducer 中取出currentTime 的放到它自己的文件。我們離開了根歸并器在一個狀態, 我們保持 currentTime 工作在根歸并器。通常來說, 我們將這些文件移動到他們自己的文檔中, 并使用rootReducer.js 文件 (我們稱之為reducers.js) 來保持主組合歸并器。
First, let"s pull the work into it"s own file in redux/currentTime.js. We"ll export two objects from here (and each reducer):首先, 讓我們把工作納入到它自己的redux/currentTime.js文件。我們將從這里 (和每個歸并器) 導出兩個對象:
initialState - 狀態樹的這個分支的初始狀態
reducer -這個分支的歸并器
import * as types from "./types"; export const initialState = { currentTime: new Date().toString(), } export const reducer = (state = initialState, action) => { switch(action.type) { case types.FETCH_NEW_TIME: return { ...state, currentTime: action.payload} default: return state; } } export default reducer
根歸并器用我們的currentTime , 我們將需要更新reducers.js 文件接受新文件到根歸并器。幸運的是, 這很簡單:
import { combineReducers } from "redux"; import * as currentUser from "./currentUser"; import * as currentTime from "./currentTime"; export const rootReducer = combineReducers({ currentTime: currentTime.reducer, currentUser: currentUser.reducer, }) export const initialState = { currentTime: currentTime.initialState, currentUser: currentUser.initialState, } export default rootReducer
最后, 讓我們更新configureStore 函數, 從文件中提取 rootReducer 和初始狀態:
import { rootReducer, initialState } from "./reducers" // ... export const configureStore = () => { const store = createStore( rootReducer, initialState, ); return store; }返回到中間件
中間件基本上是一個接受store函數, 它將返回一個接受next 函數, 這將返回一個接受動作的函數。有點亂?讓我們看看這意味著什么。
可能是最簡單的中間件讓我們構建最小的中間件, 我們可能能夠準確地理解到底發生了什么, 以及如何將它添加到我們的棧中。
讓我們創建我們的第一個中間件。
現在, 中間件的簽名看起來像這樣:
const loggingMiddleware = (store) => (next) => (action) => { // Our middleware }
對這個中間件的事情很迷惑?別擔心, 我們都是第一次看到它。讓我們把它剝離回來一點點, 拆解發生了什么事。上面的loggingMiddleware 描述可以像下面這樣重寫:
const loggingMiddleware = function(store) { // Called when calling applyMiddleware so // our middleware can have access to the store return function(next) { // next is the following action to be run // after this middleware return function(action) { // finally, this is where our logic lives for // our middleware. } } }
我們不需要擔心 怎么 被調用, 只是它確實得到了這個順序調用。讓我們增強我們的loggingMiddleware , 這樣我們實際上就可以注銷被調用的動作:
const loggingMiddleware = (store) => (next) => (action) => { // Our middleware console.log(`Redux Log:`, action) // call the next function next(action); }
Our middleware causes our store to, when every time an action is called, we"ll get a console.log with the details of the action.我們的中間件導致我們的存儲被調用,我們會得到一個console.log 動作細節。
為了將中間件應用到我們的棧中, 我們將用這個恰當命名的applyMiddleware 函數作為 createStore() 方法的第三個參數。
import { createStore, applyMiddleware } from "redux";
對于 應用 中間件, 我們可以在 createStore() 方法中調用這個 applyMiddleware() 函數。在我們的 src/redux/configureStore.js 文件中, 讓我們通過添加對applyMiddleware() 的調用來更新存儲創建:
const store = createStore( rootReducer, initialState, applyMiddleware( apiMiddleware, loggingMiddleware, ) );
現在我們的中間件已經到位。在瀏覽器中打開控制臺以查看此演示所調用的所有動作。嘗試單擊打開控制臺的Update 按鈕.。
正如我們所看到的, 中間件使我們能夠在我們的Redux動作調用鏈中插入一個函數。在該函數中, 我們可以訪問該動作、狀態, 而且我們還能夠分發其他動作。
我們希望編寫一個可以處理 API 請求的中間件函數。我們可以編寫一個中間件函數, 它只偵聽與 API 請求對應的動作。我們的中間件可以 "監視" 具有特殊標記的動作。例如, 我們可以有一個 meta 對象的行動與 type 的 "api"。我們可以使用它來確保我們的中間件不處理與 API 請求無關的任何動作:
const apiMiddleware = store => next => action => { if (!action.meta || action.meta.type !== "api") { return next(action); } // This is an api request }
如果某個動作有一個帶有 "api",類型的元對象, 我們將在 apiMiddleware.中接收該請求。
讓我們轉換我們的updateTime()actionCreator, 將這些屬性包含到一個 API 請求中。讓我們打開我們一直在使用的currentTime Redux模塊 (在src/redux/currentTime.js), 并找到fetchNewTime()函數定義。
讓我們把這個請求的 URL 傳遞給我們的meta 對象。我們甚至可以從調用動作創建者的內部接受參數:
const host = "https://andthetimeis.com" export const fetchNewTime = ({ timezone = "pst", str="now"}) => ({ type: types.FETCH_NEW_TIME, payload: new Date().toString(), meta: { type: "api", url: host + "/" + timezone + "/" + str + ".json" } })
當我們按下按鈕更新的時間, 我們的apiMiddleware 將結束了在歸并器之前截取。對于我們在中間件中捕獲的任何調用, 我們可以將元對象拆分, 并使用這些選項進行請求。或者, 我們可以通過fetch() API 將整個被消毒的meta 對象傳遞出去。
我們的 API 中間件需要采取的步驟:
從 meta 中查找請求 URL 并撰寫請求選項
提出要求
將請求轉換為 JavaScript 對象
回復Redux/用戶
讓我們采取這按步就班的步驟。首先, 關閉 URL 并創建fetchOptions 以傳遞到fetch()。我們將在下面的代碼中的注釋中列出這些步驟:
const apiMiddleware = store => next => action => { if (!action.meta || action.meta.type !== "api") { return next(action); } // This is an api request // Find the request URL and compose request options from meta const {url} = action.meta; const fetchOptions = Object.assign({}, action.meta); // Make the request fetch(url, fetchOptions) // convert the response to json .then(resp => resp.json()) .then(json => { // respond back to the user // by dispatching the original action without // the meta object let newAction = Object.assign({}, action, { payload: json.dateString }); delete newAction.meta; store.dispatch(newAction); }) } export default apiMiddleware
我們有幾個選項, 我們如何回復到Redux鏈中的用戶。就個人而言, 我們更喜歡用相同的類型響應請求被激發, 而沒有 meta 標記, 并將響應體作為新動作的 payload 有效負載 。
這樣, 我們不需要改變我們的Redux歸并器來管理響應任何不同的, 如果我們沒有提出要求。
我們也不限于一個單一的響應。假設我們的用戶在請求完成時通過了onSuccess 回調來調用。我們可以調用這個onSuccess 回調, 然后發送備份鏈:
const apiMiddleware = store => next => action => { if (!action.meta || action.meta.type !== "api") { return next(action); } // This is an api request // Find the request URL and compose request options from meta const {url} = action.meta; const fetchOptions = Object.assign({}, action.meta); // Make the request fetch(url, fetchOptions) // convert the response to json .then(resp => resp.json()) .then(json => { if (typeof action.meta.onSuccess === "function") { action.meta.onSuccess(json); } return json; // For the next promise in the chain }) .then(json => { // respond back to the user // by dispatching the original action without // the meta object let newAction = Object.assign({}, action, { payload: json.dateString }); delete newAction.meta; store.dispatch(newAction); }) }
這里的可能性幾乎是無止境的。讓我們添加apiMiddleware 到我們的鏈通過它更新configureStore() 函數:
import { createStore, applyMiddleware } from "redux"; import { rootReducer, initialState } from "./reducers" import loggingMiddleware from "./loggingMiddleware"; import apiMiddleware from "./apiMiddleware"; export const configureStore = () => { const store = createStore( rootReducer, initialState, applyMiddleware( apiMiddleware, loggingMiddleware, ) ); return store; } export default configureStore;
請注意, 我們不必更改視圖的 _任意_代碼 以更新數據在狀態樹中的填充方式。很漂亮吧?
這個中間件非常簡單, 但它是構建它的良好基礎。您是否可以考慮如何實現緩存服務, 以便我們不需要對已有的數據進行請求?如何讓一個跟蹤掛起的請求, 這樣我們就可以為未完成的請求顯示一個微調框?
太棒了!現在我們真的是Redux忍者。我們已經征服了Redux大山, 并準備繼續下一步的行動。在我們去之前, 但是..。我們已經完成了3周!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87166.html
摘要:今天我們將討論創建組件的最終方案,即無狀態函數的純組件。今天我們正在研究一種處理提出的復雜數據的方法,稱為體系結構。第天部署介紹今天,我們將探討部署我們的應用所涉及的不同部分,以便外界可以使用我們的應用。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3758原文:https://www.fullstackreact.com/3...
摘要:在方法中處理數據有三不同的角色派發器儲存視圖層我們的組件的主要思想是有一個單一源儲存他們只能通過觸發更新。這些操作負責調用派發器可以訂閱更改并相應地更新自己的數據。與不同不使用派發器而是使用純函數來定義數據變異函數。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3812原文:https://www.fullstackreact...
摘要:去營救有一種方法我們把我們的歸約器分成多個歸約器每個都只負責狀態樹的葉子。此外我們還學習了如何擴展以使用多個歸約器和動作以及多個連接的組件。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3825原文:https://www.fullstackreact.com/30-days-of-react/day-20/ 使用Redux,...
摘要:包包含由團隊提供的測試實用程序。將在一個名為的目錄中自動查找整個樹中的測試文件是的帶有下劃線。讓我們為時間軸組件創建第一個測試。其中之一是命令。現在我們已經編寫了第一個測試并確認了我們的設置我們將在明天開始測試我們的時間軸組件。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3807原文:https://www.fullstac...
摘要:歸約器函數負責返回應用當前全局狀態的表示形式。當我們在存儲上發送操作時將使用應用的當前狀態和導致狀態更新的操作來調用此歸約器函數。回到我們的歸約器我們可以檢查的動作類型并采取適當的步驟創建下一個狀態。我們將處理動作創造者中歸約器的副作用。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3811原文:https://www.ful...
閱讀 2786·2021-11-22 14:45
閱讀 2925·2021-09-10 11:26
閱讀 3231·2021-09-07 10:18
閱讀 2219·2019-08-30 14:08
閱讀 617·2019-08-29 12:22
閱讀 1393·2019-08-26 13:48
閱讀 2535·2019-08-26 10:24
閱讀 1150·2019-08-23 18:35