Redux - 中介軟體
Redux 本身是同步的,那麼像網路請求這樣的非同步操作如何在 Redux 中工作?這裡中介軟體就派上用場了。如前所述,reducers 是編寫所有執行邏輯的地方。Reducer 與誰執行它、花費多少時間或記錄操作分派前後應用程式的狀態無關。
在這種情況下,Redux 中介軟體函式提供了一種在分派的操作到達 reducer 之前與其互動的方法。可以透過編寫高階函式(返回另一個函式的函式)來建立自定義中介軟體函式,該函式圍繞某些邏輯進行包裝。可以將多箇中間件組合在一起以新增新功能,並且每個中介軟體都不需要了解之前和之後發生了什麼。您可以將中介軟體想象成操作分派和 reducer 之間的東西。
通常,中介軟體用於處理應用程式中的非同步操作。Redux 提供了一個名為 applyMiddleware 的 API,它允許我們使用自定義中介軟體以及 Redux 中介軟體(如 redux-thunk 和 redux-promise)。它將中介軟體應用於 store。使用 applyMiddleware API 的語法如下:
applyMiddleware(...middleware)
這可以應用於 store,如下所示:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
const store = createStore(rootReducer, applyMiddleware(thunk));
中介軟體將允許您編寫一個操作分派器,它返回一個函式而不是一個操作物件。下面顯示了相同內容的示例:
function getUser() {
return function() {
return axios.get('/get_user_details');
};
}
可以在中介軟體內編寫條件分派。每個中介軟體都接收 store 的 dispatch,以便它們可以分派新的操作,並將 getState 函式作為引數,以便它們可以訪問當前狀態並返回一個函式。內部函式的任何返回值都將作為 dispatch 函式本身的值可用。
以下是中介軟體的語法:
({ getState, dispatch }) => next => action
getState 函式用於確定是否要獲取新資料或返回快取結果,具體取決於當前狀態。
讓我們來看一個自定義中介軟體日誌記錄函式的示例。它只是記錄操作和新狀態。
import { createStore, applyMiddleware } from 'redux'
import userLogin from './reducers'
function logger({ getState }) {
return next => action => {
console.log(‘action’, action);
const returnVal = next(action);
console.log('state when action is dispatched', getState());
return returnVal;
}
}
現在透過編寫以下程式碼行將日誌記錄中介軟體應用於 store:
const store = createStore(userLogin , initialState=[ ] , applyMiddleware(logger));
使用以下程式碼分派一個操作以檢查分派的操作和新狀態:
store.dispatch({
type: 'ITEMS_REQUEST',
isLoading: true
})
下面是另一箇中間件示例,您可以在其中處理何時顯示或隱藏載入程式。此中介軟體在您請求任何資源時顯示載入程式,並在資源請求完成後隱藏它。
import isPromise from 'is-promise';
function loaderHandler({ dispatch }) {
return next => action => {
if (isPromise(action)) {
dispatch({ type: 'SHOW_LOADER' });
action
.then(() => dispatch({ type: 'HIDE_LOADER' }))
.catch(() => dispatch({ type: 'HIDE_LOADER' }));
}
return next(action);
};
}
const store = createStore(
userLogin , initialState = [ ] ,
applyMiddleware(loaderHandler)
);