Når du utvikler en React-applikasjon, kan det være fristende å bygge funksjoner som monolitiske komponenter, der alt logikk og struktur er samlet i én enhet. Denne tilnærmingen kan fungere på kort sikt, men det vil raskt bli uholdbart etter hvert som applikasjonen vokser. I denne delen av boken vil vi utforske hvordan vi kan forbedre strukturen på en eksisterende monolitisk komponent ved å dele den opp i mindre, mer vedlikeholdsvennlige og gjenbrukbare komponenter. Dette er en viktig ferdighet som gjør koden lettere å vedlikeholde, utvide og teste.
I utgangspunktet har vi en komponent som viser en liste med artikler. Denne komponenten inneholder både logikken for å håndtere brukerinteraksjoner og JSX-koden som definerer hvordan artiklene skal vises. Selv om denne løsningen fungerer, er det en stor ulempe ved å ha all logikk i én komponent: vedlikeholdbarheten. Hvis vi ønsker å bruke deler av denne funksjonaliteten andre steder i applikasjonen, må vi bygge om de samme funksjonene på nytt, da de ikke er gjenbrukbare.
For å forbedre dette kan vi begynne med å dele opp JSX-strukturen. Den første delen som kan brytes ut, er kontrollene for å legge til nye artikler. Dette er en selvstendig enhet som kan håndtere input, og den har ikke noe behov for å vite om hvilke artikler som er i listen eller hvordan de vises. Deretter kan vi fokusere på selve listen med artikler. Hver artikkel i listen kan potensielt være en egen komponent, som håndterer visningen og interaksjonen med hver enkelt artikkel.
Etter å ha isolert listene, kan vi bygge en ArticleList-komponent som tar ansvar for å vise listen over artikler. Denne komponenten mottar en liste med artikler som en egenskap (prop) sammen med hendelsesbehandlere som styrer hva som skjer når brukeren interagerer med artiklene. Ved å overføre ansvaret for visningen til en egen komponent, slipper vi at hovedkomponenten må håndtere visningslogikk og tilstander, og vi kan i stedet fokusere på å oppdatere og vise informasjonen som trengs.
En videre forbedring kan være å bryte ned hver artikkel i en egen komponent, ArticleItem. Her kan vi flytte logikken for å håndtere åpning og lukking av hver artikkel, samt oppdatering av visningen, til en mer lokal kontekst. Dette reduserer behovet for å oppdatere hele listen over artikler når bare én artikkel endres. Ved å bruke lokal tilstand for å håndtere om en artikkel er åpen eller lukket, kan vi forbedre ytelsen, da React ikke trenger å gjengi hele listen på nytt ved hver endring.
Når artikkellisten er delt opp i flere komponenter, er neste skritt å isolere kontroller for å legge til nye artikler. Dette kan gjøres ved å lage en egen AddArticle-komponent. Denne komponenten vil håndtere innholdet for å legge til en ny artikkel, inkludert feltene for tittel og sammendrag. Den vil også ha egne hendelsesbehandlere for å oppdatere tilstanden til inputfeltene, men den trenger ikke å vite noe om listen over eksisterende artikler.
Denne typen refaktorering bidrar til å gjøre koden mer modulær og lett å teste. Ved å bryte funksjonaliteten ned til små, gjenbrukbare komponenter, kan du enkelt endre eller utvide hver enkelt del uten at det påvirker de andre delene av applikasjonen. I tillegg blir det lettere å identifisere og fikse feil, da hver komponent har et klart ansvar.
En annen viktig aspekt ved å lage gjenbrukbare komponenter er å sørge for at de er generiske nok til å kunne brukes i forskjellige sammenhenger. Dette betyr at komponentene bør være uavhengige av spesifikke data eller statuser som tilhører den overordnede applikasjonen. I stedet bør de være designet for å motta nødvendige data og funksjoner som props, noe som gir stor fleksibilitet når det gjelder hvordan de kan brukes i forskjellige deler av appen.
Når du lager komponenter på denne måten, bør du også vurdere hvordan du kan bruke render props for å redusere avhengighetene mellom komponentene. Render props tillater at en komponent kan overføre en funksjon som lar den andre komponenten bestemme hva som skal gjengis, basert på sine egne tilstander eller data. Denne tilnærmingen kan være spesielt nyttig når du har komponenter som trenger å dele logikk uten å være direkte koblet sammen.
Det er også viktig å forstå at funksjonskomponenter i React gir en enklere og mer effektiv måte å håndtere tilstand og livssyklusmetoder på, spesielt når du bruker hooks. Ved å konvertere klassebaserte komponenter til funksjonskomponenter, kan vi forenkle koden og samtidig opprettholde all funksjonalitet.
For å oppsummere, er målet med å bryte ned monolitiske komponenter i React-applikasjoner å gjøre dem mer fleksible, vedlikeholdsvennlige og gjenbrukbare. Ved å begynne med JSX-strukturen, isolere funksjonaliteten i mindre komponenter og bruke funksjonelle komponenter og hooks, kan du bygge en mer robust og skalerbar applikasjon. Det er også viktig å huske på at komponentene bør være generiske og modulære, slik at de kan brukes på tvers av forskjellige deler av applikasjonen uten unødvendige avhengigheter.
Hvordan implementere navigasjon i React-applikasjoner ved hjelp av Drawer og Tabs
Når man bygger brukergrensesnitt i React-applikasjoner, er navigasjon en av de viktigste komponentene som må håndteres effektivt. To vanlige navigasjonsmønstre er bruk av "Drawer" og "Tabs", som begge tilbys av Material UI-biblioteket. I denne artikkelen vil vi se på hvordan man kan implementere disse navigasjonsmønstrene og hvilke detaljer som er viktige å vurdere for å skape en sømløs brukeropplevelse.
Drawer-komponenten brukes vanligvis for å vise navigasjonslenker i et skjult panel, som kan åpnes og lukkes av brukeren. Denne funksjonaliteten er spesielt nyttig på mobile enheter hvor skjermplassen er begrenset. Et viktig aspekt ved Drawer-komponenten er hvordan vi styrer synligheten av dette panelet. I koden nedenfor ser vi hvordan dette kan gjøres:
Her bruker vi en enkel betingelse for å håndtere tastetrykk og avgjøre om draweren skal åpnes eller lukkes. Den åpne tilstanden (open) kontrollerer om Drawer er synlig eller ikke. Denne tilstanden endres hver gang funksjonen setOpen kalles, noe som kan skje både gjennom en brukerhandling som klikking på et ikon, eller gjennom andre hendelser som å aktivere en lenke i draweren.
Når det gjelder lenkene som vises i Drawer-komponenten, er de generert fra et array av objekter som inneholder både URL og navnet på lenken. Hver lenke knyttes til en navigasjonskommando som gir brukerens applikasjon en aktiv rute. Her er et eksempel på hvordan lenkene er definert:
Når en lenke er aktivert, endres synligheten av draweren, og innholdet på siden oppdateres i henhold til den valgte ruten. Det er også viktig å merke seg at lenken som representerer den aktive ruten, får en spesiell stil for å markere hvilken side brukeren er på.
Et annet navigasjonsmønster som vi finner ofte i moderne webapplikasjoner, er bruk av tabs. Tabs er alltid synlige og gir en rask måte for brukeren å navigere mellom forskjellige seksjoner av applikasjonen. Material UI tilbyr en Tabs-komponent som kan brukes til å lage et tab-basert navigasjonssystem. Slik kan et slikt system implementeres:
I eksemplet over har vi definert tre forskjellige ruter som er knyttet til hver sin tab. Når en tab klikkes på, oppdateres URL-en, og innholdet som vises på siden, endres i henhold til hvilken tab som er aktiv. For å håndtere hvilken tab som skal være aktiv, kan man bruke useRouteMatch-hooken til å sjekke den nåværende URL-en og sammenligne den med de forskjellige rutenavnene:
Ved å bruke denne metoden kan vi holde styr på hvilken tab som skal være aktiv, basert på den nåværende URL-en. Dette gir brukeren en intuitiv og responsiv navigasjonserfaring.
I tillegg til Drawer og Tabs finnes det mange andre komponenter som Material UI tilbyr for å forbedre brukergrensesnittet, som for eksempel skjemaelementer for å samle inn data fra brukere. Det er viktig å merke seg at det er en rekke detaljer som må tas i betraktning for å få en god brukeropplevelse, spesielt når det gjelder å håndtere interaktive komponenter som sjekkbokser, radioknapper og tekstfelt. Hver av disse komponentene er designet for å være fleksible og brukervennlige, men det er nødvendig å sørge for at de er riktig konfigurert og tilpasset den spesifikke applikasjonen.
Endtext
Hvorfor React Native Reanimated er bedre enn Animated API
I React Native-økosystemet finnes det mange biblioteker og tilnærminger for å animere komponenter, inkludert den innebygde Animated API-en. Men i denne sammenhengen ønsker jeg å fokusere på et bibliotek kalt React Native Reanimated og sammenligne det med den originale Animated API-en for å vise hvorfor det er det beste valget.
Animated API-en er det mest brukte verktøyet for å animere komponenter i React Native. Den inneholder en rekke metoder som lar deg lage et animasjonsobjekt, kontrollere tilstanden og håndtere prosessene som er nødvendige for animasjonen. Den største fordelen med denne API-en er at den kan brukes med alle typer komponenter, ikke bare animerte komponenter som View eller Text. Likevel har denne API-en sine begrensninger, ettersom den ble implementert i React Natives gamle arkitektur. Kommunikasjon mellom JavaScript-tråden og UI-tråden skjer asynkront, noe som fører til forsinkelse i oppdateringene på minst ett skjermbilde (ca. 16 ms), og i enkelte tilfeller kan forsinkelsen være enda lenger hvis JavaScript-tråden er opptatt med Reacts diff-algoritme eller nettverksforespørsler.
Problemet med forsinkede eller droppede bilder kan imidlertid løses med React Native Reanimated-biblioteket, som er bygget på den nyeste arkitekturen. I stedet for å bruke den gamle asynkrone kommunikasjonen, behandler React Native Reanimated all forretningslogikk fra JavaScript-tråden i UI-tråden, og gjør animasjonene mye mer responsive.
React Native Reanimated gir en mer omfattende abstraksjon av Animated API-en og lar oss lage mer komplekse animasjoner og tilpassede overganger. Dette skjer gjennom et imperativt API som gir oss muligheten til å jobbe med flertrinnede animasjoner, samtidig som det også tilbyr et deklarativt API for enkle animasjoner, som fungerer på samme måte som CSS-overganger. En stor fordel med React Native Reanimated er at det benytter "worklets", som er JavaScript-funksjoner som kan kjøres synkront i UI-tråden. Dette betyr at animasjoner kan kjøres umiddelbart uten å vente på et nytt skjermbilde, noe som eliminerer forsinkelsen.
Et enkelt eksempel på en worklet-funksjon kan se slik ut:
For at worklet-funksjonen skal bli kalt i UI-tråden, er det eneste som kreves at vi legger til worklet-direktivet øverst i funksjonsblokken.
React Native Reanimated tilbyr flere hooks og metoder som gjør animasjoner lettere å håndtere. For eksempel:
-
useSharedValue: Denne hooken returnerer en SharedValue-instans, som er hovedobjektet for tilstandshåndtering i UI-tråden. Denne verdien kan oppdateres uten å trigge en ny rendering, og gir muligheten til å kjøre komplekse animasjoner på 60 FPS uten å blokkere JavaScript-tråden.
-
useDerivedValue: Denne hooken lar deg opprette en delt verdi som automatisk oppdateres når kildene som den er avhengig av endres. Denne kan benyttes for å lage derivert tilstand som påvirker animasjoner uten å tvinge en ny rendering av UI.
-
useAnimatedStyle: Med denne hooken kan du lage et stilobjekt som kan animere egenskapene sine basert på de delte verdiene. Det er den viktigste måten å koble sammen de delte verdiene med visningskomponentene og gjøre animasjoner mer flytende.
-
withTiming, withSpring, withDecay: Dette er nyttige metoder som definerer hvordan animasjoner skal oppdateres, enten ved å bruke glatte kurver, fysikkbaserte bevegelser eller andre tilpasninger.
I tillegg til funksjonaliteten til React Native Reanimated, er installasjonen av biblioteket enkel. Ved å bruke Expo, kan du installere biblioteket ved å kjøre følgende kommando:
Deretter må du legge til Babel-plugin-en i babel.config.js for at JavaScript-funksjonene skal kunne kjøres i UI-tråden:
Etter at du har lagt til denne plugin-en, er det nødvendig å starte utviklingsserveren på nytt og tømme bundleren sin cache:
Ved å bruke React Native Reanimated kan man animere komponenter på en mer effektiv og responsiv måte, og unngå forsinkelsene som oppstår med den eldre Animated API-en. Dette gir en mye bedre brukeropplevelse, særlig når du arbeider med komplekse eller dynamiske brukergrensesnitt.
Når du arbeider med React Native Reanimated, er det også viktig å merke seg hvordan animasjoner kan brukes til å forbedre brukergrensesnittets interaktivitet. For eksempel, animasjoner for å vise eller skjule komponenter, som å gjøre en knapp animert ved hover eller trykk, eller bruke enkle effekter som "FadeIn" og "ZoomIn" for å vise innhold, kan gjøre applikasjonen mer levende og engasjerende for brukeren. Reanimated tilbyr enkle måter å animere elementer ved innlasting eller ved avslutning (for eksempel å bruke entering og exiting-props for å definere forhåndsdefinerte animasjoner). Dette er spesielt nyttig når du lager applikasjoner med dynamiske lister eller interaktive elementer.
Det er også viktig å være oppmerksom på ytelsen. Animasjoner som kan kjøre på 60 FPS gir en jevnere og mer profesjonell følelse. Bruken av UI-tråden for animasjonene minimerer latens og forsinkelse, noe som kan være spesielt synlig på mobile enheter med lavere prosesseringskapasitet. Å forstå de ulike API-ene og metodene som React Native Reanimated tilbyr vil hjelpe deg å lage applikasjoner som er både effektive og visuelt attraktive.
Hvordan React har utviklet seg og hvorfor det er viktig for utviklere
React er et av de mest populære verktøyene for utvikling av brukergrensesnitt, og har gjennomgått en imponerende utvikling siden det ble introdusert. Det er et verktøy som har vært med på å endre hvordan vi bygger moderne webapplikasjoner. Men hvorfor har React blitt så populært, og hva er det som gjør det så spesielt?
Et av de mest fundamentale prinsippene i React er abstraksjonen av renderingsmiljøet. React gjør det mulig å beskrive brukergrensesnittet uten å være bundet til et spesifikt mål for rendering, som en nettleser eller mobilplattform. Dette gjør at React kan brukes på tvers av ulike miljøer som React DOM for nettlesere, React Native for mobilutvikling, React PDF for dokumentgenerering, og til og med React Unity for å bygge interaktive 3D-opplevelser. Dette gir en utrolig fleksibilitet og muligheten til å gjenbruke kode på tvers av plattformer.
En av de mest imponerende egenskapene ved React er hvor lett det er å tilpasse seg nye teknologier og plattformer. Hver gang React introduserer en ny versjon, er det stort fokus på å opprettholde stabiliteten samtidig som det legges til nye funksjoner og forbedringer. For utviklere er dette en stor fordel, da man kan bruke React-kunnskapene på tvers av flere plattformer og versjoner uten å måtte lære helt nye prinsipper eller paradigmer.
React har utviklet seg betydelig gjennom årene. Fra de tidlige versjonene har det blitt introdusert flere banebrytende funksjoner som har revolusjonert måten vi utvikler applikasjoner på. Versjon 0.14 introduserte for eksempel funksjonelle komponenter, som gjorde det lettere å lage grunnleggende brukergrensesnitt. Men det var først med versjon 16 at React virkelig ble en kraftig plattform med introduksjonen av hooks. Hooks, som useState og useEffect, har gjort det mulig å bruke tilstand og andre funksjoner uten å måtte bruke klassekomponenter. Dette har forenklet koden betydelig og gjort den mer lesbar.
React 16 introduserte også Fiber, en ny mekanisme for å håndtere rekonsiliering, som har forbedret ytelsen betraktelig. Dette var spesielt viktig for applikasjoner med komplekse brukergrensesnitt eller animasjoner, da det gjorde det mulig å håndtere store endringer i UI på en mer effektiv måte.
React 18, som fokuserte på ytelsesforbedringer og nye funksjoner som automatisk batching av rendering og serverkomponenter, har vært en viktig oppdatering som har gjort React enda mer kraftfullt og effektivt. Denne versjonen har også introdusert streaming server-side rendering, som gir bedre ytelse for applikasjoner som genereres på serveren.
React 19 tar dette et steg videre med flere forbedringer, som en ny kompilator for automatisk memoization og optimering av rendering. Det gjør at utviklere kan unngå å bruke funksjoner som useMemo eller useCallback manuelt, og forenkler dermed utviklingsprosessen. React 19 introduserer også enklere API-er og forbedret feilhåndtering, noe som gjør det lettere å diagnostisere og fikse problemer i applikasjoner.
Denne kontinuerlige utviklingen og forbedringen av React betyr at det forblir relevant og kraftfullt, både for nybegynnere og erfarne utviklere. I tillegg til de tekniske forbedringene som er nevnt, er React stabilt nok til å være et pålitelig valg for langvarige prosjekter.
Når man setter opp et nytt React-prosjekt, er det flere tilnærminger som kan brukes. En vanlig måte å komme i gang på er ved hjelp av web bundlere som Vite, som gjør oppsettet raskt og effektivt. For mer komplekse prosjekter, spesielt kommersielle applikasjoner, er det vanlig å bruke rammeverk som Next.js, Gatsby, eller Remix. Disse rammeverkene tilbyr ekstra funksjonalitet som ruting, håndtering av bilder og SVG-filer, og forbedret prosjektstruktur.
Vite er et populært valg for mange utviklere, da det tilbyr utrolig rask oppstartstid og enkel konfigurasjon. For å komme i gang med Vite, er det første trinnet å sikre at Node.js er installert på datamaskinen. Deretter kan man raskt opprette et nytt React-prosjekt ved å bruke kommandoen npm create vite@latest og følge instruksjonene for å installere nødvendige avhengigheter og starte utviklingsserveren.
Bruken av rammeverk som Next.js kan være spesielt nyttig når man jobber med server-side rendering eller statisk nettstedgenerering, noe som gjør det mulig å lage raske og skalerbare applikasjoner. I kapittel 13 vil vi gå dypere inn på hvordan Next.js kan brukes sammen med React for å bygge slike applikasjoner.
Det som er viktig å forstå om React, er at det ikke bare handler om en spesifikk versjon eller funksjon. Det er en filosofi som handler om å gjøre UI-utvikling enklere og mer effektiv ved å bruke komponenter og abstrahere bort detaljer om plattformen. React gir utviklere et rammeverk som kan brukes til å lage alt fra enkle nettsider til komplekse applikasjoner på tvers av plattformer.

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский