Norsk

Utforsk React-hooken useEvent, et kraftig verktøy for å skape stabile referanser til hendelseshåndterere i dynamiske React-applikasjoner, forbedre ytelsen og forhindre unødvendige re-renders.

React useEvent: Oppnå stabile referanser til hendelseshåndterere

React-utviklere støter ofte på utfordringer når de håndterer hendelseshåndterere (event handlers), spesielt i scenarier som involverer dynamiske komponenter og closures. Hooken useEvent, et relativt nytt tilskudd til React-økosystemet, gir en elegant løsning på disse problemene. Den lar utviklere skape stabile referanser til hendelseshåndterere som ikke utløser unødvendige re-renders.

Forstå problemet: Ustabilitet i hendelseshåndterere

I React blir komponenter re-rendret når deres props eller state endres. Når en funksjon for en hendelseshåndterer sendes som en prop, blir det ofte opprettet en ny funksjonsinstans ved hver re-rendering av foreldrekomponenten. Denne nye funksjonsinstansen, selv om den har samme logikk, anses som forskjellig av React, noe som fører til re-rendering av barnekomponenten som mottar den.

Se på dette enkle eksempelet:


import React, { useState } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    console.log('Klikket fra Parent:', count);
    setCount(count + 1);
  };

  return (
    

Antall: {count}

); } function ChildComponent({ onClick }) { console.log('ChildComponent rendret'); return ; } export default ParentComponent;

I dette eksempelet blir handleClick gjenopprettet ved hver re-rendering av ParentComponent. Selv om ChildComponent kan være optimalisert (f.eks. ved hjelp av React.memo), vil den likevel re-rendres fordi onClick-propen har endret seg. Dette kan føre til ytelsesproblemer, spesielt i komplekse applikasjoner.

Introduksjon til useEvent: Løsningen

Hooken useEvent løser dette problemet ved å gi en stabil referanse til funksjonen for hendelseshåndtereren. Den frikobler effektivt hendelseshåndtereren fra re-renderingssyklusen til foreldrekomponenten.

Selv om useEvent ikke er en innebygd React-hook (per React 18), kan den enkelt implementeres som en "custom hook", eller i noen rammeverk og biblioteker tilbys den som en del av deres verktøysett. Her er en vanlig implementering:


import { useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // useLayoutEffect er avgjørende her for synkrone oppdateringer
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // Avhengighetslisten er bevisst tom for å sikre stabilitet
  ) as T;
}

export default useEvent;

Forklaring:

Bruk av useEvent i praksis

La oss nå refaktorere det forrige eksempelet ved å bruke useEvent:


import React, { useState, useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // useLayoutEffect er avgjørende her for synkrone oppdateringer
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // Avhengighetslisten er bevisst tom for å sikre stabilitet
  ) as T;
}

function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleClick = useEvent(() => {
    console.log('Klikket fra Parent:', count);
    setCount(count + 1);
  });

  return (
    

Antall: {count}

); } function ChildComponent({ onClick }) { console.log('ChildComponent rendret'); return ; } export default ParentComponent;

Ved å pakke inn handleClick med useEvent, sikrer vi at ChildComponent mottar den samme funksjonsreferansen på tvers av re-renderinger av ParentComponent, selv når count-state endres. Dette forhindrer unødvendige re-renderinger av ChildComponent.

Fordeler med å bruke useEvent

Bruksområder for useEvent

Alternativer og hensyn

Selv om useEvent er et kraftig verktøy, finnes det alternative tilnærminger og hensyn å ta:

Hensyn til internasjonalisering og tilgjengelighet

Når man utvikler React-applikasjoner for et globalt publikum, er det avgjørende å ta hensyn til internasjonalisering (i18n) og tilgjengelighet (a11y). useEvent i seg selv påvirker ikke i18n eller a11y direkte, men det kan indirekte forbedre ytelsen til komponenter som håndterer lokalisert innhold eller tilgjengelighetsfunksjoner.

For eksempel, hvis en komponent viser lokalisert tekst eller bruker ARIA-attributter basert på gjeldende språk, kan det å sikre at hendelseshåndterere i den komponenten er stabile forhindre unødvendige re-renderinger når språket endres.

Eksempel: useEvent med lokalisering


import React, { useState, useContext, createContext, useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // useLayoutEffect er avgjørende her for synkrone oppdateringer
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // Avhengighetslisten er bevisst tom for å sikre stabilitet
  ) as T;
}

const LanguageContext = createContext('en');

function LocalizedButton() {
  const language = useContext(LanguageContext);
  const [text, setText] = useState(getLocalizedText(language));

  const handleClick = useEvent(() => {
    console.log('Knapp klikket på', language);
    // Utfør en handling basert på språket
  });

  function getLocalizedText(lang) {
      switch (lang) {
        case 'en':
          return 'Click me';
        case 'fr':
          return 'Cliquez ici';
        case 'es':
          return 'Haz clic aquí';
        default:
          return 'Click me';
      }
    }

    //Simuler språkendring
    React.useEffect(()=>{
        setTimeout(()=>{
            setText(getLocalizedText(language === 'en' ? 'fr' : 'en'))
        }, 2000)
    }, [language])

  return ;
}

function App() {
  const [language, setLanguage] = useState('en');

  const toggleLanguage = useCallback(() => {
    setLanguage(language === 'en' ? 'fr' : 'en');
  }, [language]);

  return (
    
      
); } export default App;

I dette eksempelet viser komponenten LocalizedButton tekst basert på gjeldende språk. Ved å bruke useEvent for handleClick-håndtereren sikrer vi at knappen ikke re-rendres unødvendig når språket endres, noe som forbedrer ytelsen og brukeropplevelsen.

Konklusjon

Hooken useEvent er et verdifullt verktøy for React-utviklere som ønsker å optimalisere ytelse og forenkle komponentlogikk. Ved å gi stabile referanser til hendelseshåndterere, forhindrer den unødvendige re-renderinger, forbedrer lesbarheten i koden og øker den generelle effektiviteten til React-applikasjoner. Selv om det ikke er en innebygd React-hook, gjør dens enkle implementering og betydelige fordeler den til et verdifullt tilskudd i enhver React-utviklers verktøykasse.

Ved å forstå prinsippene bak useEvent og dens bruksområder, kan utviklere bygge mer ytelsessterke, vedlikeholdbare og skalerbare React-applikasjoner for et globalt publikum. Husk å alltid måle ytelsen og vurdere de spesifikke behovene til applikasjonen din før du bruker optimaliseringsteknikker.

React useEvent: Oppnå stabile referanser til hendelseshåndterere i dynamiske React-applikasjoner | MLOG