Denne lille artikkelserien introduserer deg til en rekke små React hooks som er praktiske å ha i kodebasen din.
Denne gangen skal vi se på hvordan man kan finne skjermstørrelsen appen er åpen i.
(PS: kode24 har fått seg nye kodebokser. Last sida på nytt et par ganger om du ikke får pene, fargelagte kodebokser!)
Inner-størrelse og resize-events 📏
Vi kan hente ut størrelsen på window-objektet for å få tak i høyde og bredde på skjermen som brukes gjennom innerWidth og innerHeight propertyene.
Da ville “hooken” vår sett noe sånn her ut:
const useWindowSize = () => ({
width: window.innerWidth,
height: window.innerHeight
})
Ikke særlig spennende (eller stateful). Men kanskje enda viktigere, den ville kun gitt deg størrelsene på skjermen i det komponenten din ble rendret for første gang.
For å få med oss når brukere endrer vindusstørrelsen må vi gjøre litt mer.
Én første tilnærming er å lage en useEffect som holder verdiene våre oppdatert, med window-propsa som dependencies. Hooken vil da se slik ut:
import { useEffect, useState } from 'react';
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight
})
}, [window.innerHeight, window.innerWidth]);
return windowSize
}
🚨 ERRR! Vi får en advarsel:
"React Hook useEffect has unnecessary dependencies: 'window.innerHeight' and 'window.innerWidth'. Either exclude them or remove the dependency array. Outer scope values like 'window.innerHeight' aren't valid dependencies because mutating them doesn't re-render the component"
Denne forteller oss at det å bruke propsene til window ikke vil fungere i et dependency array, og vi må finne en annen kløktig løsning for å holde verdiene oppdatert. 🤔
Skjul og vis i React med useDisclosure: - Blitt skikkelig fan av hooken
Her kommer resize-eventet oss til unnsetning. Istedenfor å sette opp dependencies mot properties fra window, kan vi når hooken rendres første gang, sette opp en event-lytter som forteller oss når skjermen har endret størrelse.
Da får man den ferdige koden som ser sånn her ut:
import { useEffect, useState } from 'react';
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const resizeEvent = () => setWindowSize({
width: window.innerWidth,
height: window.innerHeight
});
window.addEventListener('resize', resizeEvent);
return () => window.removeEventListener('resize', resizeEvent);
}, []);
return windowSize;
};
P.S: Det er røddig å fjerne en EventListener når man er ferdig med den. Det gjør man i retur-verdien av useEffect.
Når du skal bruke hooken blir det kanskje litt som det her:
const phoneMaxWidth = 768;
const Navbar = () => {
const {width} = useWindowSize();
return (
<nav className="navbar">
{width > phoneMaxWidth && <Menu/>}
{width < phoneMaxWidth && <PhoneMenu/>}
</nav>
);
};
Media Query-måten
Kanskje har man lyst til å finne ut litt mer om klienten?
En annen fremgangsmåte er å bruke window sin matchMedia metode, som gir muligheten for å bruke media queries fra CSS-verdenen.
Sånn lagrer du state lokalt i React - uten cookie
Teknikken er relativt lik som den forrige, med en useEffect som setter opp en EventListener, men denne gangen på et MediaQueryList-objekt vi får fra matchMedia metoden. Vi blir også nødt å få inn en media query, som useEffect-en vil ha i dependency arrayet.
Hooken blir da seende slik ut:
export function useMediaQuery(query: string) {
const [matches, setMatches] = useState(false);
useEffect(() => {
const media = window.matchMedia(query);
const changeEvent = () => {
setMatches(media.matches);
};
media.addEventListener("change", changeEvent);
return () => media.removeEventListener("change", (changeEvent));
}, [query]);
return matches;
}
Og i samme bruks-eksempel som over vil se slik ut:
const Navbar = () => {
const isPhone = useMediaQuery('(max-device-width: 768px)');
return (
<nav className="navbar">
{!isPhone && <Menu/>}
{isPhone && <PhoneMenu/>}
</nav>
);
};
Og littegrann ekstra 💅
Denne hooken gir også muligheter for å gjøre andre typer media queries en bare vindusstørrelse.
For eksempel kan du bruke prefers-color-scheme: dark for å finne ut om brukeren foretrekker dark-mode, eller velge og vrake i en haug andre kule media queries!
React-hook: Kopiere ting til utklippstavla
Har du en krok-idé?
Vi har en rekke enkle hooks som er greie å ha i verktøykassa. Om du har en du er spesielt fornøyd med, så send oss en mail — så kan det godt hende den dukker opp i denne serien!