React 中間件:連接 API 與元件

中介軟體在網頁開發中並不是一個新概念。它通常與像 Express.js 這樣的後端框架相關聯,因為那裡涉及大量的身份驗證、日誌記錄等。由於其固有的優勢,中介軟體在前端也獲得了顯著的關注。

前端框架如 React 正在採用它作為在狀態管理過程中處理複雜功能的一種方式。在本指南中,我們將引導您了解 React 中的中介軟體概念,以及如何使用它來增強您的 React 應用程序的功能並有效管理應用程序流程。

到最後,您將對 React 中介軟體有一個良好的理解,以及如何與 Redux Thunk 一起實現它。

簡化的 React 中介軟體:精簡應用程序邏輯

什麼是中介軟體?

顧名思義,中介軟體是一個位於應用程序不同組件之間的層。它在此提供了一層處理和功能,當沒有它時將不會存在這一層。中介軟體通過攔截從一個組件流向另一個組件的請求來運作,並允許您執行特定的操作。一旦完成,它將修改過的請求傳遞給下一個中介軟體或其預定的目的地。

這是一個主要用於後端的概念。但正如前面提到的,它已在 React 中被適應以服務於類似的目的。現在,讓我們深入了解中介軟體在 React 中的意義。

React 中的中介軟體

在React中,中间件是作为一系列函数实现的,按照您定义的顺序依次执行。每个函数都可以访问应用程序的状态和操作。因此,这些函数可以修改并分发新的操作。

在React中状态发生变化时,应用程序会分发操作,然后由Reducer处理这些操作。Reducer将返回一个新的状态,然后将其存储并传递回应用程序。

React中间件位于分发的操作和到达Reducer之前拦截它。然后,它允许您钩入此过程并在此操作上执行一些代码,例如记录它或进行API调用。

完成此操作后,它将修改后的操作传递给Reducer(如果链中没有其他中间件)。

React中的中间件示例

您可以在主要使用复杂状态管理React库的Redux中找到React中间件。Redux有两种主要类型的中间件:

  • Thunk – 我们将深入探讨如何使用此中间件来修改操作。
  • Saga。

它们各自处理对操作的不同类型修改,我们将在查看React中间件的用途时进行更详细的了解。其他React库,如React Query,也使用中间件(稍后详细介绍)。

在看如何实现之前,让我们先看一下React中间件的不同用途。

React中间件的用途

React 中間件對以下用例非常有用:

調試和記錄

React 中間件可用於在應用程序開發期間記錄當前狀態、操作和其他數據等信息。此外,這些中間件可用於識別潛在的錯誤和問題,以便及早解決。

Redux Logger(用於 Redux)可幫助您實現此目的。它會記錄 Redux 操作和狀態變化,以便輕鬆進行調試。它會攔截每個已發送的操作並記錄先前的狀態、操作和下一個狀態。

授權和驗證

如果您想在更新狀態之前對用戶進行身份驗證,可以使用 Redux Thunk 或 Saga 來處理身份驗證工作流程。一旦攔截了一個操作,這個中間件使您能夠存儲令牌,在發送操作之前檢查身份驗證,或刷新令牌。

換句話說,這些中間件對於檢查用戶是否經過身份驗證以訪問特定路由非常有用。

事件驅動操作

React reducer 設計用於運行同步代碼。這意味著如果您試圖在其上運行任何異步任務,將無法運行。使用 React 中間件(如 Redux Thunk),您可以捕獲操作,執行像發出 API 調用這樣的異步任務,並在完成後繼續到 reducer。

緩存數據

React Query(另一個React中間件)可以作為緩存應用程序數據的有效工具。它會自動緩存API響應並在需要時重新驗證它們。因此,它幫助您通過在緩存中查找所需信息來避免冗餘的API調用。

性能增強

React中間件還可以通過延遲不必要的操作、篩選事件以及批處理某些任務來增強應用程序的性能。通過緩存API響應,React Query還可以增強您的React應用程序的性能。

如何在React中使用中間件?

Redux是在React應用程序中管理全局狀態的強大工具。它包含了幾個中間件,您可以使用這些中間件來為React應用程序添加自定義功能。其中最常見的是Redux Thunk

Redux Thunk簡介

在深入實現Thunk之前,讓我們先收集一些關於它的信息,以便我們可以有效地使用它。

Thunk是什麼?

在一般編程中,Thunk簡單地是一個用於延遲評估和執行函數的函數。我們可以將它看作是一個推遲動作直到特定條件滿足的函數。

在Redux中,thunk是一個與Redux Thunk中間件一起使用的特定函數。Redux Thunk旨在允許您的React應用程序執行異步操作。之前提到過,Reducer是設計用於運行同步代碼的。這意味著當一個動作被分發時,減速器會立即更新狀態。

Redux Thunk作為中間件

Redux Thunk充當中間件。它允許您編寫返回函數(thunks)而不是普通動作對象的動作創建器。這些函數可以包含異步邏輯。當您派發一個thunk時,Thunk中間件會攔截它並執行該函數。

thunk內部,您可以執行異步操作(例如,發出API調用),然後在操作完成時派發常規動作以更新Redux存儲。

注意:Redux Thunk允許同時執行異步和同步操作,儘管其主要目的是促進異步操作。它不會阻止您派發同步操作,它只是提供一個處理異步操作的機制。

說了這些,讓我們通過實現Redux Thunk來看React中間件的作用。

實現Redux Thunk的逐步指南

實現Redux中間件涉及以下步驟:

步驟1:使用Thunk設置Redux

創建一個React應用程序並安裝依賴項。

Plain Text

 

npx create-react-app newApp

步驟2:安裝Redux Thunk

運行以下命令來安裝Redux Thunk

Plain Text

 

npm install redux-thunk

步驟3:啟用Thunk中間件

JavaScript

 

Enable the Thunk middleware in the Redux store.

import { configureStore } from '@reduxjs/toolkit';
import thunk from 'redux-thunk';
import rootReducer from './reducers'; // Combine all reducers here

const store = configureStore({
reducer: rootReducer,
middleware: [thunk],
});

export default store;

注意: 使用Redux Toolkit時,無需显式安裝thunk

步驟 4:編寫異步函數

一個 thunk 返回另一個函數,該函數接收dispatchgetstate參數以讀取狀態或分派操作。以下是獲取數據的示例代碼:

JavaScript

 

// 操作類型
const START_FETCH = 'START_FETCH';
const FETCH_SUCCESS = 'FETCH_SUCCESS';
const FETCH_ERROR = 'FETCH_ERROR';

  // 操作創建者
const startFetch = () => ({ type: START_FETCH });
const fetchSuccess = (data) => ({ type: FETCH_SUCCESS, payload: data });
const fetchError = (error) => ({ type: FETCH_ERROR, payload: error });

  // Thunk 操作
export const fetchData = () => {
return async (dispatch, getState) => {
      dispatch(startFetch()); // Notify that the fetch has started

try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Failed to fetch data');
}
const data = await response.json();

        dispatch(fetchSuccess(data)); // Send the fetched data to the store
} catch (error) {
         dispatch(fetchError(error.message)); // Handle any errors
}
};
  };

步驟 5:在 Reducer 中處理分派的操作

通過更新 reducer 來處理分派的操作。

JavaScript

 

const initialState = {
data: [],
    isLoading: false,
    error: null,
};

export const dataReducer = (state = initialState, action) => {
switch (action.type) {
case START_FETCH:
return { ...state, isLoading: true, error: null };
case FETCH_SUCCESS:
return { ...state, isLoading: false, data: action.payload };
case FETCH_ERROR:
return { ...state, isLoading: false, error: action.payload };
default:
return state;
}
  };

步驟 6:從組件分派 Thunk

在 React 項目中使用useDispatch鉤子來分派 thunk。

JavaScript

 

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchData } from './actions';

const DataComponent = () => {
const dispatch = useDispatch();
const { data, isLoading, error } = useSelector((state) => state.data);

useEffect(() => {
      dispatch(fetchData()); // Trigger the thunk to fetch data
}, [dispatch]);

if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;

return (
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
};

export default DataComponent;

使用 createAsyncThunk

Redux Toolkit 包含一個內置 API,該 API 定義了異步函數的高級邏輯,分派它們並及時處理錯誤。請注意,由於這為異步函數的特定用例提供了一種抽象,createAsyncThunk不適用於所有 thunk 的用例。

以下是createAsyncThunk的示例實現:

JavaScript

 

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

export const dataFetch = createAsyncThunk('data/fetchData', async () => {
const response = await fetch('https://api.example.com/data');
return response.json();
});

const dataSlice = createSlice({
    name: 'data',
    initial_State: { data: [], loading: false, error: null },
extraReducers: (builder) => {
builder
.addCase(dataFetch.pending, (state) => {
          state.loading = true;
          state.error = null;
})
.addCase(dataFetch.fulfilled, (state, action) => {
          state.loading = false;
state.data = action.payload;
})
.addCase(dataFetch.rejected, (state, action) => {
          state.loading = false;
state.error = action.error.message;
});
},
});

export default dataSlice.reducer;

現在,要分派dataFetch thunk,請使用以下代碼:

JavaScript

 

dispatch(dataFetch ());

React 中間件 Redux Thunk 的用途

Thunks 可用於各種用途,包括但不限於:

  • 從組件中抽象出複雜的邏輯。
  • 進行異步請求和邏輯。
  • 編寫函數以按系列分派多個操作。

React 中的其他狀態管理庫的中介軟體

Redux 並不是唯一一個利用中介軟體的 React 庫。你也可以在其他狀態管理庫中找到它們,儘管這些庫中對這一概念的實現方式與 Redux 中的方式有所不同。

MobX

MobX 沒有像 Redux 那樣的傳統中介軟體。它通過攔截器、觀察者和反應等機制提供類似的功能。這些機制允許你觀察 MobX 狀態的變化並對其做出反應。這樣,MobX 提供了處理副作用、日誌記錄和其他中介軟體通常在 Redux 中處理的任務的方法。

Recoil

Recoil 不像 Redux 那樣支持中介軟體,因為它不需要。它允許你使用特定函數直接更新狀態的部分(原子)。沒有將行動派發給 reducer 的過程,這可以被中介軟體攔截。為了處理異步操作,它使用選擇器——依賴於原子或其他選擇器的派生狀態。

Zustand

它通過簡單的 API 幫助管理狀態,並支持原生中介軟體用於日誌記錄和存儲狀態,就像 Redux 一樣。

XState

XState 通過使用 onTransitionactionsservices 這樣的鉤子來支持類似中介軟體的行為。這些鉤子有助於攔截和修改狀態轉換。

結論

中介軟體作為橋樑,連接和結合網頁應用程序的不同組件,以改善數據流和處理。自那時以來,它們在後端得到了廣泛應用,但現在在前端也找到了用例。

在 React 中,有多種方法來實現中介軟體。它們通常與狀態管理庫如 Redux 和 MobX 相關聯。最常用的 React 中介軟體,Thunk,包含在 Redux 庫中。Thunk 是一個執行延遲任務的代碼區塊。

在本文中,我們探討了 React 中的中介軟體、Redux 庫以及 Redux Thunk。我們還涵蓋了實現 Redux Thunk 中介軟體 以獲取數據和調度操作的步驟。

Source:
https://dzone.com/articles/demystifying-react-middleware-bridging-apis-and-co