Gjenbrukbare komponenter er de mest nyttige, men også de vanskeligste å lage på en god måte. Her finner du noen gode tips til hvordan man kan lage en gjenbrukbare komponent som tåler tidens tann!
En av de tingene jeg setter mest pris på med React, er komponentmodellen. Denne modellen gir oss en skikkelig nyttig abstraksjon når det kommer til å bygge grensesnitt.
- Du kan trekke ut en vilkårlig del av applikasjonen og bruke den på nytt andre steder
- Du kan definere hvilke deler av komponenten som skal kunne påvirkes utenfra og ikke
- Den fungerer fra en noe så enkelt som en
div
til en hel app
Komponenter er litt som funksjoner (vel, rent teknisk så er de vel akkurat som funksjoner): Noen ganger lager man en komponent som en måte å strukturere koden sin på i litt mindre deler, som det er enklere å forstå, og andre ganger trekker man ut gjentakende deler av koden sin for å bruke den mange ganger.
Det er de gjentakende komponentene denne artikkelen skal handle om. For hvis man først skal lage kode man kan bruke mange steder på tvers av appen sin (eller i noen tilfeller, på tvers av hundrevis av produktteam), så er det viktig at man har tenkt nøye gjennom et par ting.
- Den må være intuitiv å bruke
- Den må kunne få nye features uten å føre til breaking changes
- Den må treffe balansen mellom meningsbærende og fleksibel
- Den må være veldokumentert
Denne artikkelen dykker ned i hva disse fire punktene vil si, og hva du kan gjøre med din egen kodebase for å få bedre gjenbrukbare komponenter.
Gjenbrukbare komponenter er intuitive å bruke
Den aller viktigste tingen du må huske på når du lager komponenter som skal brukes flere ganger, er at de må være enkle å bruke. Det finnes forskjellige måter å definere enkel på, men jeg liker at ting er intuitivt. Man… skjønner liksom hvordan man skal bruke komponenten, helt uten å ha lest noe som helst av hverken kode eller dokumentasjon. Man kan la brukeren (altså, utvikleren) "gjette" hvilke props som finnes, og gi dem rett mesteparten av tiden.
Måten du oppnår denne intuisjonen på er å være konsekvent med hvordan du navngir props. På denne måten lar du folk gjenbruke læringen sin fra en annen gjenbrukbar komponent til den neste.
Eksempler på props-navn jeg pleier å bruke er:
variant
– hvis man har flere forskjellige varianter av hvordan en komponent ser ut, bruker man variant
-propen. Denne lar deg definere om noe har default utseende, om den er outlined, ghost (uten outline) eller sekundær.size
– mange komponenter kommer i forskjellige størrelser. La derfor brukerne dine definere denne størrelsen på samme vis overaltcolorScheme
– om komponenten din støtter forskjellige farger, som skal kombineres med forskjellige varianter, kan det være nyttig å ha en colorScheme
-propisSomething
– om du skal ha boolske props i komponenten din, så er det fint å prefikse dem med is
. Det kommuniserer intensjonen til propen din, gjør den enklere å gjenkjenne, og den leser bedre (vel, det synes jeg i alle fall).
I tillegg til props-navn, kan verdiene også være greit å standardisere. Størrelser bør følge tskjortestørrelser (xl, lg, md, sm osv), og varianter kan også fint ha de samme navnene (primary, secondary, default, ghost, outline, muted osv). Velg de verdiene som gir mening i din kontekst.
Det at ting er intuitivt, betyr ikke at alt trenger å være likt overalt. Alle komponenter trenger ikke å ha en størrelse, og langt ifra alle trenger en variant. Men når man først bruker dem, er det fint at de har de samme navnene. Det gjør komponentene dine lettere å bruke!
Gjenbrukbare komponenter bør få nye features uten å føre til breaking changes
Gjenbrukbare komponenter har en tendens til å bli brukt mange steder. Noen ganger brukes de internt i én kodebase, mens andre ganger brukes de på tvers av haugevis av kodebaser. Felles for begge disse scenarioene er at å endre hvordan de brukes på tvers av alle bruksstedene, er en slitsom oppgave.
Derfor – tenk litt over hvordan komponentene dine er designet fra et API-perspektiv før du setter deg ned og implementerer dem.
En typisk måte man skyter seg i foten på er å bruke boolske props. Der det hadde vært enklest å lage en isLarge
-prop når du får meldt inn et behov om å ha en større versjon av komponenten din, så er det oftest bedre at du innfører en string-prop som tar imot en av flere predefinerte verdier (som sm, md eller lg, for eksempel). Da slipper du å refaktorere all koden din når du skal implementere at komponenten din skal kunne være bitteliten også.
Av og til må du legge til props også. Men med mindre det er en spesielt god grunn, så burde den nye propen ha en default-verdi som gjør det som var standarden før den nye propen kom inn. Da kan folk spesifisere den nye propen når de trenger en åpen
Men selv om breaking changes er slitsomme, så trengs de av og til. Noen ganger bør du påkreve at man fyller ut en aria-attributt for å opprettholde god universell utforming, og andre ganger trenger du rett og slett å gjøre en god gammel refaktorering for å fjerne gammel kode eller øke fleksibiliteten. Men gjør ditt beste for å unngå dem! De er dyre og kjipe for alle involverte.
Gjenbrukbare komponenter treffer balansen mellom meningsbærende og fleksibel
Av og til er det ganske deilig at komponenter kommer innebygget med noen meninger. Det gjør det lettere å ta i bruk, og du får beskjed om hva du må ha med for å få ting til å både oppleves bra, og være universelt utformet.
Et eksempel kan være en ikon-knapp som krever at du oppgir et ikon og en beskrivende tekst for skjermlesere. Et annet kan være en tabell-komponent som bare tar imot en liste med objekter. Det gjør API-flaten til komponenten din enklere å forstå, og ofte mye mindre verbos.
Men noen ganger trenger man å ha fleksibiliteten til å bryte ned en mer kompleks komponent i mindre bestanddeler. En tabell kan ha behov for å kunne ha både ikoner og sorteringsfunksjonalitet i headerne sine, og av og til trenger man bare kalender-biten av en datepicker. Da kan det være nyttig å være fleksibel.
Det jeg ofte anbefaler er at man lager et veldig fingranulert API for komplekse komponenter. Har du en tabell, burde du la folk sette den sammen selv ved hjelp av enkle komponenter som Table
, Thead
, Tr
, Th
og Td
. En modal kan også dekomponeres til komponenter som Modal
, ModalBackdrop
, ModalBody
og ModalFooter
. Det gjør at du kan lage hva du vil, uten å reimplementere hele komponenten.
Når du har gjort dette, kan du så sette sammen mer komplekse komponenter som SimpleModal
eller SortableTable
, som gir et forenklet API til de mest vanlige usecasene, samtidig som man lar folk være fleksible når man trenger det. Det sparer deg også fra å legge til haugevis med props for å støtte alle mulige rare bruksområder - som igjen ville ført til at komponenten din var vanskeligere å bruke.
Gjenbrukbare komponenter må være veldokumenterte
Dokumentasjon er fantastisk når den er fantastisk, og en kjempebyrde når den er horribel, manglende, vanskelig å finne eller – verre – utdatert. Derfor er det viktig å gjøre det riktig.
Måten jeg anbefale komponenter på, er via flittig bruk av JSDoc-kommentarer. De kan du bruke både på komponentnivå og på props-nivå.
På komponentnivå kan du forklare intensjonen bak komponenten og hva den gjør. Du bør komme med eksempler på de vanligste måtene den kan brukes på, ting man bør tenke på rundt universell utforming, eller hvordan de forskjellige variantene bør brukes fra et designperspektiv.
På et props-nivå kan du forklare hva propen gjør, når den burde brukes, og hva som skjer om du utelater den. Her kan du også legge til eksempler og retningslinjer for bruk – for eksempel at man kun skal ha en primærknapp per skjermbilde, eller at man aldri burde bruke en combobox dersom det er under 10 elementer å velge mellom.
Målet til en godt dokumentert komponent er at utvikleren burde få svar på alle spørsmålene sine gjennom å hovre komponenten i VS Code. Og om noen skal endre på koden en gang i fremtiden, så er det enkelt å forstå hvordan ting fungerer. Sure, det finnes eksempler der det kan være nyttig med en dokumentasjonsside i tillegg – men det er i så fall for å hensynta andre brukere enn utviklere.
Gjenbrukbare komponenter er nyttige i mer enn designsystemer
Hvis du har lest deg ned hit, så sitter du sikkert igjen med en tanke om at "jada, Kristofer, men det er ikke alle som jobber med designsystemer hver dag." Og det er definitivt viktigst å følge disse rådene når du jobber med komponenter i et designsystem – komponenter som brukes tusenvis av ganger i titalls kodebaser. Men vil du ikke også være enig i at dette er ting som gjør det bedre å bruke kode uansett om den skal gjenbrukes tre eller tre tusen ganger?
Sannheten er at dette er endringer du kan gjøre til din egen arbeidsflyt som fører til komponenter som er lettere å bruke, enklere å forstå, og mindre arbeid å forbedre på et senere tidspunkt. Ikke tar det så mye tid å implementere heller. Om du virkelig hater dokumentasjon, så kan du jo få generativ AI til å lage et godt førsteutkast (det gjør jeg), eller dra ned scopet på hvilket nivå du vil legge deg på, et par hakk.
Jeg håper du fant litt inspirasjon til å forbedre komponentene du lager, og hvordan de oppleves av både deg selv og andre i tiden fremover.