Skjul og vis i React med useDisclosure: - Blitt skikkelig fan av hooken

Kaptein Krok viser deg hvordan du enklere husker hva som skal vises. - Et mønster som gjentar seg til det kjedelige.

Kristofer Giltvedt Selbekk er en helt vanlig utvikler på dagtid. På kveldstid tar han på seg sånn rar hatt og trebein, og blir Kaptein Krok. 📸: Ole Petter Baugerød Stokke
Kristofer Giltvedt Selbekk er en helt vanlig utvikler på dagtid. På kveldstid tar han på seg sånn rar hatt og trebein, og blir Kaptein Krok. 📸: Ole Petter Baugerød Stokke Vis mer

Denne lille artikkelserien introduserer deg til en rekke små React hooks som er praktiske å ha i kodebasen din.

Denne utgaven gir deg et utrolig nyttig verktøy som også er utrolig lett å lage — eller piratkopiere, om du vil.

Å vise eller ikke vise 💀

En ting jeg gjør mye når jeg skriver React-kode, er å huske på om noe skal vises eller ei. Det kan være en dialog eller modal, en advarsel eller kanskje en bildekarusell.

Den tilstanden lagrer jeg som regel i en useState på denne måten:

const [isOpen, setOpen] = React.useState(false);

Så endrer jeg denne tilstanden med en knapp, eller en callback, for eksempel.

const [isOpen, setOpen] = React.useState(false);
return (
  <>
    <button onClick={() => setOpen(true)}>Åpne</button> 
    {isOpen && <EnModal onClose={() => setOpen(false)} />}
  </>
);

Av og til skal man kanskje kunne rett og slett slå ting av og på også!

const [isOpen, setOpen] = React.useState(false);
return (
  <>
    <button onClick={() => setOpen(prev => !prev)}>
      {isOpen ? 'Skjul' : 'Vis'} instruksjoner
    </button> 
    {isOpen && <Instruksjoner />}
  </>
);

Dette er et mønster som gjentar seg til det kjedelige. Kanskje vi kan lage en hook som gjør det bare ett hakk lettere?

Hils på useDisclosure

Det fine med custom hooks i React, er at det gjør det enkelt og lavterskel å lage gjenbrukbar kode. Selv når koden du abstraherer bort er så enkel som den kan få blitt.

Her er en hook jeg kaller useDisclosure som gjør koden over hakket enklere å lese:

const useDisclosure = (defaultOpen: false) => {
  const [isOpen, setOpen] = React.useState(defaultOpen);
  const onOpen = React.useCallback(() => setOpen(true), []);
  const onClose = React.useCallback(() => setOpen(false), []);
  const onToggle = React.useCallback(
    () => setOpen(prev => !prev), 
    []
  );
  return { isOpen, onOpen, onClose, onToggle };
}

Her har vi flyttet React.useState-kallet inn i en custom hook, og laget egne navngitte funksjoner for å åpne, lukke og snu isOpen -tilstanden. Alt returneres i et objekt som enkelt kan destruktureres slik man vil.

💡 Merk at alle funksjonene er wrappet i hver sin React.useCallback hook. Det er så de ikke skal trigge unødvendige re-renders. Det er ofte en optimalisering man ikke trenger å gjøre, men når man skal lage generiske hooks kan det være greit å gjøre det “just in case”.

Og her er koden over skrevet om til å bruke denne hooken:

const { isOpen, onOpen, onClose } = useDisclosure();
return (
  <>
    <button onClick={onOpen}>Åpne</button> 
    {isOpen && <EnModal onClose={onClose} />}
  </>
);

Og siste eksemplet også da, bare for å være helt komplett:

const { isOpen, onToggle } = useDisclosure();
return (
  <>
    <button onClick={onToggle}>
      {isOpen ? 'Skjul' : 'Vis'} instruksjoner
    </button> 
    {isOpen && <Instruksjoner />}
  </>
);

Koden blir lettere å lese, og det er færre anonyme pilfunksjoner rundt om i koden vår!

Trenger man det da?

Nei, man gjør jo åpenbart ikke det.

For å være ærlig tok det meg noen uker å bli vant til å bruke denne hooken — det er jo ikke så mye kode som dras ut, og det ekstra leddet med omdirigering gjør at man kanskje må innom en ekstra fil første gangen man bruker denne for å se hva som skjer.

Til tross for alt dette har jeg blitt en skikkelig fan av denne hooken. Det forenkler koden min, og jeg får fokusert på å kode mer spennende ting. Også kan den jo testes helt for seg selv — så du slipper å skrive egne tester for det samme. Win win!

Har du en krok-idé?

Jeg har en rekke enkle hooks som er greie å ha i verktøykassa. Om du har en du er spesielt fornøyd med, så send meg en mail — så kan det godt hende den dukker opp i denne serien!