En jämförelse av datahämtningskrokar i React

By rik

React-hooks erbjuder ett effektivt sätt att hantera sidoeffekter inom React-komponenter. Bland de vanligaste verktygen för detta ändamål finns `useEffect`, `useLayoutEffect` och `useEffectEvent`. Varje hook är designad för specifika användningsfall, vilket gör det viktigt att välja rätt verktyg för uppgiften.

`useEffect`-Hooken

`useEffect`-hooken är en grundläggande del av React som ger möjligheten att utföra sidoeffekter som DOM-manipulation, asynkrona operationer och datahämtning inuti funktionella komponenter. Denna hook tar emot två argument: effektfunktionen och beroendearrayen.

Effektfunktionen innehåller den kod som ska exekvera sidoeffekten, medan beroendearrayen styr när effektfunktionen körs. Om beroendearrayen är tom, kommer effektfunktionen endast att köras en gång, vid den initiala renderingen av komponenten. Annars aktiveras effektfunktionen varje gång ett av värdena i beroendearrayen ändras.

Här är ett exempel som illustrerar hur `useEffect`-hooken används för att hämta data:

 import React from "react";

function App() { const [data, setData] = React.useState([]);

React.useEffect(() => { fetch("<https://jsonplaceholder.typicode.com/posts>") .then((response) => response.json()) .then((data) => setData(data)); }, []);

return ( <div className="app"> {data.map((item) => ( <div key={item.id}>{item.title}</div> ))} </div> ); } export default App;

I detta kodexempel visas en appkomponent som använder `useEffect`-hooken för att hämta data från ett externt API. Effekten hämtar data från JSONPlaceholder API, tolkar det JSON-formaterade svaret och lagrar den hämtade informationen i ett state.

Komponenten renderar sedan `title`-egenskapen för varje objekt i det hämtade datat.

Egenskaper hos `useEffect`-Hooken

  • Asynkront stöd: Inbyggt stöd för asynkrona operationer, vilket underlättar datahämtning.
  • Exekvering efter rendering: `useEffect`-hooken kör sina effekter efter att komponenten har renderats, vilket säkerställer att den inte blockerar användargränssnittet.
  • Rensning: Inbyggt stöd för rensning av resurser genom att returnera en funktion. Speciellt användbart för lyssnare eller prenumerationer.

`useLayoutEffect`-Hooken

`useLayoutEffect`-hooken liknar `useEffect`-hooken men körs synkront *efter* alla DOM-ändringar. Det innebär att den körs innan webbläsaren ritar om skärmen, vilket gör den lämplig för uppgifter som kräver noggrann kontroll över DOM-layout och stilar, såsom att mäta elementstorlek, ändra elementstorlek eller animera positioner.

Här är ett exempel på hur man använder `useLayoutEffect`-hooken för att ändra bredden på ett knappelement:

 import React from "react";

function App() { const button = React.useRef();

React.useLayoutEffect(() => { const { width } = button.current.getBoundingClientRect();

button.current.style.width = `${width + 12}px`; }, []);

return ( <div className="app"> <button ref={button}>Click Me</button> </div> ); } export default App;

I exemplet ovan ökar bredden på knappelementet med 12 pixlar genom användning av `useLayoutEffect`-hooken. Detta säkerställer att knappens bredd justeras innan knappen visas på skärmen.

Egenskaper hos `useLayoutEffect`-Hooken

  • Synkront utförande: Körs synkront, vilket kan leda till att användargränssnittet blockeras om operationerna inuti är tunga.
  • DOM-läsning/skrivning: Bäst lämpad för att läsa och skriva direkt till DOM, särskilt om ändringarna krävs innan webbläsaren ritar om skärmen.

`useEffectEvent`-Hooken

`useEffectEvent`-hooken är en React-hook som är avsedd att lösa de problem med beroenden som kan uppstå med `useEffect`-hooken. Om du är bekant med `useEffect` vet du att dess beroendearray kan vara komplicerad. Ibland kan man behöva inkludera fler värden i beroendearrayen än vad som är absolut nödvändigt.

Till exempel:

 import React from "react";

function App() { const connect = (url) => { };

const logConnection = (message, loginOptions) => { };

const onConnected = (url, loginOptions) => { logConnection(`Connected to ${url}`, loginOptions); };

React.useEffect(() => { const device = connect(url); device.onConnected(() => { onConnected(url); }); return () => { device.disconnect(); }; }, [url, onConnected]);

return <div></div>; } export default App;

Det här kodexemplet illustrerar en appkomponent som hanterar en anslutning till en extern tjänst. Funktionen `connect` etablerar en anslutning till en given URL, medan `logConnection` loggar anslutningsdetaljer. Funktionen `onConnected` anropar `logConnection` för att logga ett meddelande om lyckad anslutning när enheten ansluts.

`useEffect`-hooken anropar `connect`-funktionen och sätter sedan upp en `onConnected`-callback som körs när enheten utlöser en `onConnected`-händelse. Denna callback loggar ett anslutningsmeddelande. Hooken returnerar en rensningsfunktion som aktiveras när komponenten avmonteras. Denna funktion ansvarar för att koppla ifrån enheten.

Beroendearrayen innehåller variabeln `url` och funktionen `onConnected`. Appkomponenten kommer att återskapa `onConnected`-funktionen vid varje rendering. Detta kommer att leda till att `useEffect`-funktionen körs i en loop, vilket orsakar att appkomponenten omrenderas i oändlighet.

Det finns flera sätt att hantera problemet med `useEffect`-loopen. Men det mest effektiva sättet att lösa det utan att lägga till onödiga värden i beroendearrayen är genom användning av `useEffectEvent`-hooken.

 import React from "react";

function App() { const connect = (url) => { };

const logConnection = (message, loginOptions) => { };

const onConnected = React.useEffectEvent((url, loginOptions) => { logConnection(`Connected to ${url}`, loginOptions); });

React.useEffect(() => { const device = connect(url); device.onConnected(() => { onConnected(url); }); return () => { device.disconnect(); }; }, [url]);

return <div></div>; } export default App;

Genom att omge `onConnected`-funktionen med `useEffectEvent`-hooken kan `useEffectEvent` alltid läsa de senaste värdena för `message` och `loginOptions` innan de skickas till `useEffect`-hooken. Detta innebär att `useEffect` inte behöver förlita sig på `onConnected`-funktionen eller de värden som skickas till den som beroenden.

`useEffectEvent`-hooken är användbar när du vill att din `useEffect` ska bero på ett specifikt värde, även om effekten utlöser en händelse som kräver andra värden som du helst inte vill använda som beroenden i `useEffect`.

Egenskaper hos `useEffectEvent`-Hooken

  • Bäst lämpad för händelsedrivna sidoeffekter.
  • `useEffectEvent`-hooken fungerar inte med händelsehanterare som `onClick`, `onChange` etc.

Observera att `useEffectEvent`-hooken fortfarande är experimentell och inte tillgänglig i React version 18-hooks.

När ska vilken hook användas?

Var och en av de ovan nämnda hookarna för datahämtning är lämplig för olika situationer:

  • Datahämtning: `useEffect` är ett utmärkt val.
  • Direkta DOM-manipulationer: Om du behöver synkront utföra ändringar i DOM innan en omritning, välj `useLayoutEffect`.
  • Enklare operationer: För operationer som inte riskerar att blockera användargränssnittet kan du använda `useEffect`.
  • Händelsedrivna sidoeffekter: Använd `useEffectEvent`-hooken för att hantera händelser och `useEffect`-hooken för att utföra sidoeffekterna.

Hantera sidoeffekter effektivt

React-hooks öppnar upp en värld av möjligheter. En förståelse för skillnaderna mellan `useEffect`, `useLayoutEffect` och `useEffectEvent` kan i hög grad påverka hur du hanterar sidoeffekter och DOM-manipulation. Det är viktigt att beakta de specifika kraven och konsekvenserna av varje hook för att skapa användarvänliga applikationer.