React 中间件:连接 API 和组件

中间件在网页开发中并非新概念。通常与后端框架如Express.js相关联,那里有很多认证、日志记录等。由于其固有优势,中间件在前端领域获得了显著的发展。

诸如React之类的前端框架正在采用它作为处理状态管理期间复杂功能的一种方式。在本指南中,我们将带您了解React中的中间件概念以及如何使用它来增强React应用的功能并有效管理应用程序流程。

最终,您将对React中间件以及如何使用Redux Thunk实现它有很好的掌握。

React中间件简化:简化应用程序逻辑

什么是中间件?

顾名思义,中间件是位于应用程序不同组件之间的一层。它在这里提供了一个处理和功能层,如果没有它,就不会有这样的一层。中间件通过拦截从一个组件流向另一个组件的请求,并允许您执行特定操作来工作。完成后,它将修改后的请求传递给下一个中间件或其预期目的地。

这是一个主要用于后端的概念。但是,正如前面提到的,它已被调整在React中发挥类似的作用。现在,让我们深入了解中间件在React中的具体含义。

React中的中间件

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

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

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

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

React中的中间件示例

你可以主要在Redux中找到React中间件,这是一个复杂的状态管理React库。Redux有两种主要类型的中间件:

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

它们各自处理不同类型的操作修改,我们将在下面查看React中间件用法时看到。其他React库,例如React Query,也使用中间件(稍后详细介绍)。

在我们看如何实现这一点之前,让我们回顾一下React中间件的不同用法。

React中间件的用途

React 中间件 在以下使用情况下非常有用:

调试和日志记录

React 中间件可用于在应用程序开发过程中记录当前状态、操作和其他数据等信息。此外,它们对于识别潜在的错误和 bug 并进行早期解决非常有帮助。

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是专为运行同步代码而构建的。这意味着当一个操作被派发时,Reducer会立即更新状态。

Redux Thunk作为中间件

Redux Thunk充当中间件。它允许您编写返回函数(thunks)而不是普通动作对象的动作创建器。这些函数可以包含异步逻辑。当您分发一个thunk时,Thunk中间件会拦截它并执行该函数。

thunk内部,您可以执行您的异步操作(例如,进行API调用),然后在操作完成时分发常规动作以更新Redux存储。

注意:Redux Thunk允许异步和同步操作,尽管其主要目的是促进异步操作。它不会阻止您分发同步动作;它只是提供一种处理异步操作的机制。

有了这个基础,让我们通过实现Redux Thunk来看React中间件的运作。

实现Redux Thunk的逐步指南

实现Redux中间件包括以下步骤:

第1步:使用Thunk设置Reduxp

创建一个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,定义了异步函数的高级逻辑,分发它们,并及时处理错误。请注意,由于这提供了对异步函数特定用例的抽象,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等钩子。这些钩子有助于拦截和修改状态转换。

结论

中间件充当桥梁,连接和组合 Web 应用程序的不同组件,以实现更好的数据流和处理。它们自从在后端广泛使用以来,现在在前端也发现了用例。

在 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