Middleware is geen nieuw concept in webontwikkeling. Het wordt doorgaans geassocieerd met backend-frameworks zoals Express.js, waar veel authenticatie, logging, enz. plaatsvindt. Vanwege de inherente voordelen heeft middleware aanzienlijke invloed gekregen in de frontend.
Frontend-frameworks zoals React nemen het over als een manier om complexe functionaliteiten tijdens state management te behandelen. In deze handleiding zullen we je door het concept van middleware in React leiden en laten zien hoe je het kunt gebruiken om de functionaliteit van je React-app te verbeteren en de toepassingsstroom effectief te beheren.
Tegen het einde zul je een goed begrip hebben van wat React-middleware is en hoe je het kunt implementeren met Redux Thunk.
React Middleware Vereenvoudigd: Stroomlijnen van toepassingslogica
Wat Is Middleware?
Zoals de naam al aangeeft, is middleware een laag die zich tussen verschillende componenten van een applicatie bevindt. Het biedt hier een verwerkings- en functionaliteitslaag wanneer die er anders niet zou zijn. Middleware werkt door verzoeken te onderscheppen die van de ene component naar de andere stromen en stelt je in staat om specifieke acties uit te voeren. Zodra dit is voltooid, wordt het gewijzigde verzoek doorgegeven aan de volgende middleware of zijn beoogde bestemming.
Dit is een concept dat voornamelijk wordt gebruikt in de backend. Maar, zoals eerder vermeld, is het aangepast in React om een vergelijkbaar doel te dienen. Laten we nu dieper ingaan op wat middleware betekent, specifiek in React.
Middleware in React
In React wordt middleware geïmplementeerd als een reeks functies die één na de ander worden uitgevoerd, in de volgorde waarin je ze definieert. Elke functie heeft toegang tot de status en acties van de app. Daarom kunnen de functies nieuwe acties wijzigen en verzenden.
Wanneer de status verandert in React, verzendt de applicatie acties die vervolgens door de Reducer(s) worden behandeld. De Reducer(s) zullen dan een nieuwe status retourneren, die vervolgens wordt opgeslagen en teruggegeven aan de applicatie.
React middleware bevindt zich tussen de verzonden actie en onderschept deze voordat deze de reducer bereikt. Vervolgens stelt het je in staat om in dit proces in te haken en wat code op deze actie uit te voeren, bijvoorbeeld door het te loggen of een API-aanroep te doen.
Als dit is gedaan, zal het de gewijzigde actie doorgeven aan de Reducer (als er geen andere middleware in de keten is).
Voorbeelden van Middleware in React
Je kunt React middleware voornamelijk vinden in Redux, de complexe statusbeheersingsbibliotheek voor React. Redux heeft twee hoofdtypen middleware:
- Thunk – we zullen dieper ingaan op hoe je deze middleware kunt gebruiken om een actie te wijzigen.
- Saga.
Elk van hen behandelt verschillende types van wijzigingen aan acties, zoals we hieronder zullen zien wanneer we kijken naar de toepassingen van middleware in React. Andere React-bibliotheken, zoals React Query, maken ook gebruik van middleware (hierover later meer).
Voordat we bekijken hoe we dit kunnen implementeren, laten we de verschillende toepassingen van middleware in React doornemen.
Toepassingen van Middleware in React
React middleware is handig voor de volgende gebruiksscenario’s:
Debuggen en Loggen
React-middleware kan worden gebruikt om informatie zoals de huidige status, acties en andere gegevens vast te leggen tijdens de ontwikkeling van de applicatie. Bovendien kunnen deze nuttig zijn voor het identificeren van potentiële bugs en fouten voor vroegtijdige oplossing.
De Redux Logger (voor Redux) kan je hierbij helpen. Het logt Redux-acties en statuswijzigingen voor eenvoudig debuggen. Het onderschept elke uitgevoerde actie en logt de vorige status, actie en de volgende status.
Autorisatie en Authenticatie
Als je gebruikers wilt authenticeren voordat je de status bijwerkt, kun je Redux Thunk of Saga gebruiken om de authenticatieworkflows te beheren. Zodra je een actie onderschept, stelt deze middleware je in staat om tokens op te slaan, authenticatie te controleren voordat de actie wordt uitgevoerd, of tokens te vernieuwen.
Met andere woorden, deze middleware is handig om te controleren of een gebruiker geauthenticeerd is om een bepaalde route te benaderen of niet.
Gebeurtenisgestuurde bewerkingen
De React-reducer is ontworpen om synchrone code uit te voeren. Dit betekent dat als je iets asynchroons probeert uit te voeren, dit niet zal werken. Met React-middleware zoals Redux Thunk kun je de actie onderscheppen, asynchrone taken uitvoeren zoals het maken van een API-oproep, en doorgaan naar de reducer zodra dit is voltooid.
Gegevens Cachen
React Query (een andere React middleware) kan dienen als een effectief hulpmiddel voor het cachen van applicatiegegevens. Het cachet API-antwoorden automatisch en valideert ze opnieuw wanneer dat nodig is. Dit helpt je om overbodige API-aanroepen te vermijden door te controleren op de vereiste informatie in de cache.
Prestatieverbetering
React middleware kan ook helpen de prestaties van de applicatie te verbeteren door onnodige acties uit te stellen, gebeurtenissen te debouncen en bepaalde taken in batches te verwerken. Door API-antwoorden te cachen, verbetert React Query ook de prestaties van je React-apps.
Hoe gebruik je middleware in React?
Redux is een krachtig hulpmiddel voor het beheren van de globale status in React-toepassingen. Het bevat verschillende middleware in zijn toolkit die je kunt gebruiken om aangepaste functionaliteit aan je React-apps toe te voegen. Een van de meest voorkomende is Redux Thunk.
Inleiding tot Redux Thunk
Voordat we diep ingaan op de implementatie van Thunk, laten we wat informatie verzamelen over het zodat we het effectief kunnen gebruiken.
Wat is Thunk?
In de algemene programmering is een “Thunk” eenvoudigweg een functie die wordt gebruikt om de evaluatie en uitvoering van een functie uit te stellen. We kunnen het beschouwen als een functie die een actie uitstelt totdat aan een specifieke voorwaarde is voldaan.
In Redux is een thunk een specifieke functie die wordt gebruikt met de Redux Thunk middleware. Redux Thunk is ontworpen om asynchrone operaties binnen je React-app mogelijk te maken. Eerder hebben we genoemd dat de Reducer is gebouwd om synchrone code uit te voeren. Dit betekent dat wanneer een actie wordt verzonden, de reducer de status onmiddellijk bijwerkt.
Redux Thunk als Middleware
Redux Thunk fungeert als middleware. Het stelt je in staat om action creators te schrijven die functies (thunks) retourneren in plaats van gewone action-objecten. Deze functies kunnen asynchrone logica bevatten. Wanneer je een thunk dispatcht, onderschept de Thunk middleware het en voert het de functie uit.
Binnen de thunk
kun je je asynchrone bewerking uitvoeren (bijv. een API-aanroep doen) en vervolgens reguliere acties dispatchen om de Redux-store bij te werken wanneer de bewerking is voltooid.
Opmerking: Redux Thunk staat zowel asynchrone als synchrone bewerkingen toe, hoewel het primaire doel is om asynchrone acties te vergemakkelijken. Het voorkomt je niet om synchrone acties te dispatchen; het biedt eenvoudig een mechanisme voor het afhandelen van asynchrone acties ook.
Dat terzijde, laten we React middleware in actie zien door Redux Thunk te implementeren.
Een Stapsgewijze Gids voor het Implementeren van Redux Thunk
Het implementeren van Redux middleware omvat de volgende stappen:
Stap 1: Stel Up Redux met Thunk
Maak een React-toepassing en installeer de afhankelijkheden.
npx create-react-app newApp
Stap 2: Installeer Redux Thunk
Voer de volgende opdracht uit om Redux Thunk te installeren.
npm install redux-thunk
Stap 3: Schakel Thunk Middleware In
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;
Opmerking: Bij het gebruik van Redux Toolkit is het niet nodig om thunk
expliciet te installeren.
Stap 4: Het schrijven van een Async Functie
Een thunk retourneert een andere functie die de argumenten dispatch
en getState
ontvangt om de status te lezen of acties te dispatchen. Hieronder staat een voorbeeldcode voor het ophalen van gegevens:
// Actie types
const START_FETCH = 'START_FETCH';
const FETCH_SUCCESS = 'FETCH_SUCCESS';
const FETCH_ERROR = 'FETCH_ERROR';
// Actie makers
const startFetch = () => ({ type: START_FETCH });
const fetchSuccess = (data) => ({ type: FETCH_SUCCESS, payload: data });
const fetchError = (error) => ({ type: FETCH_ERROR, payload: error });
// Thunk actie
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
}
};
};
Stap 5: Afhandelen van Gedispachte Acties in Reducer
Handel de gedispachte acties af door de reducer bij te werken.
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;
}
};
Stap 6: Dispatchen van een Thunk vanuit een Component
Gebruik de useDispatch
hook om thunks te dispatchen in React-projecten.
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;
Het gebruik van createAsyncThunk
De Redux Toolkit bevat een ingebouwde API die hoog-niveau logica definieert voor asynchrone functies, deze dispatcht en fouten snel afhandelt. Let op dat aangezien dit een abstractie biedt voor specifieke gebruiksscenario’s van asynchrone functies, createAsyncThunk
niet van toepassing is op alle gebruiksscenario’s van thunks.
Hieronder staat de voorbeeldimplementatie van createAsyncThunk
:
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;
Om nu de dataFetch
thunk te dispatchen, gebruik de volgende code:
dispatch(dataFetch ());
Gebruik van React Middleware – Redux Thunk
Thunks kunnen voor verschillende doeleinden worden gebruikt, waaronder maar niet beperkt tot:
- Complexe logica abstraheren vanuit de componenten.
- Asynchrone verzoeken en logica maken.
- Functies schrijven om meerdere acties in serie te dispatchen.
React Middleware in Andere Statusbeheerlibraries
Redux is niet de enige React-bibliotheek die gebruik maakt van middleware. Je kunt ze ook vinden in andere statusbeheerlibraries, hoewel de implementatie van dit concept in deze libraries verschilt van hoe het in Redux wordt gedaan.
MobX
MobX heeft geen traditionele middleware zoals Redux. Het biedt vergelijkbare functionaliteit via mechanismen zoals interceptors, observers en reacties. Deze mechanismen stellen je in staat om veranderingen in je MobX-status te observeren en daarop te reageren. Op deze manier biedt MobX manieren om bijwerkingen, logging en andere taken te beheren die middleware typisch behandelt in Redux.
Recoil
Recoil ondersteunt middleware niet op dezelfde manier als Redux omdat het dat niet nodig heeft. Het stelt je in staat om direct delen van de status (atomen) bij te werken met specifieke functies. Er is geen verzending van acties naar een reducer, die je met middleware kunt onderscheppen. Voor het afhandelen van asynchrone operaties maakt het gebruik van selectors — afgeleide status afhankelijk van atomen of andere selectors.
Zustand
Het helpt bij het beheren van statussen met een eenvoudige API en ondersteunt native middleware voor logging en het opslaan van statussen, net als Redux.
XState
XState ondersteunt middleware-achtige gedragingen met behulp van hooks zoals onTransition
, actions
, en services
. Deze hooks helpen om statusovergangen te onderscheppen en te wijzigen.
Conclusie
Middleware fungeert als een brug om verschillende componenten van een webtoepassing te verbinden en te combineren voor een betere gegevensstroom en -verwerking. Ze worden al geruime tijd veel gebruikt op de backend, maar hebben nu ook toepassingen gevonden op de frontend.
In React zijn er verschillende manieren om de middleware te implementeren. Ze zijn meestal gekoppeld aan de statusbeheerbibliotheken zoals Redux en MobX. De meest gebruikte React-middleware, Thunk, is opgenomen in de Redux-bibliotheek. Een thunk is een codeblok dat de vertraagde taken uitvoert.
In dit artikel hebben we Middleware in React, Redux-bibliotheek, en Redux Thunk verkend. We hebben ook de stappen behandeld om Redux Thunk-middleware te implementeren voor het ophalen van gegevens en het verzenden van acties.
Source:
https://dzone.com/articles/demystifying-react-middleware-bridging-apis-and-co