Ditlev Tøjner: React’s simple tilgang til webapplikationer

Selvom der hersker et til tider kaotisk miljø omkring JavaScript og frontend development – med et utal af libraries, ideologier, meninger og patterns – er React i sig selv et simpelt og robust koncept.
Bag React står Facebook, der har haft en massiv udfordring med skalering af deres software. De har taget webcomponent-ideen og skabt et spændende og produktivt udviklermiljø omkring sig, både ift. dokumentation og developer tools, men lige så meget en udbredelse af open source-komponenter, der er nemme at integrere i eksisterende React-projekter. Onlinebetaling bliver pludselig meget nemmere – ingen popups og redirects, fordi Stripe tilbyder et open source React library.

 

React

React involverer to primære principper, der efterfølgende kan understøttes og udbygges med et utal af værktøjer og metoder, der er forbundet med frontend-udvikling og JavaScript-sprogets mange muligheder for at håndtere abstraktioner; objects, this, bind, promises, prototypes, class.

  1. React skaber komponenter
  2. React indsætter disse komponenter i en DOM, som brugeren kan interagere med og ændre tilstand på i applikationen.

Disse komponenter ender med at blive HTML, CSS, Javascript, som kan pakkes og serveres med en HTML-fil.

Komponenter

Den simpleste React-komponent, ser ud som følger. Facebook har splittet React op i flere dele. Fordi vi arbejder med browseren, benytter vi os af ‘react-dom’. Resultatet af dette er et <div> HTML-tag med en <H1> heading, med indholdet High Five. Dette bliver indsat i et HTML-element med id’et root.

Import react from 'react'

Import ReactDOM from 'react-dom'

class App extends React.Component {

render() {

return (
<div><h1>High Five</h1></div>
)
}
}

ReactDOM.render(<App/>, document.getElementById("root"))

Stateful- og Stateless-komponenter

I React arbejder vi med to forskellige slags komponenter alt efter, om der skal arbejdes med en tilstand i komponenten, eller om komponenten blot skal rendere data. Det vil sige, at hvis der er behov for, at komponent skal arbejde med intern tilstand – vi vil eksempelvis gerne holde styr på, om brugeren har trykket på en knap, eller skrevet noget i et søgefelt – har det behov for at kunne arbejde med This. I de tilfælde, hvor vi ønsker at arbejde med tilstand, gør vi det ved at lytte på events på de elementer, vi ønsker at reagere på og binde dette op på komponentens This.

Brugerinteraktion

class App extends React.Component {

render() {

return (
<div><h1>High Five</h1></div>
)
}
}

class App extends React.Component {

constructor() {

super()

this.state = {name:"Ditlev"}
}

render() {

return (

<div>

<label>Skriv dit navn</label>

<input type="text"
value={this.state.name}
onChange={(e) => this.setState({name:e.target.value})} />

</div>

)
}
}

ReactDOM.render(<App/>, document.getElementById("root"))
 
Vi har et tekstfelt med en reference til værdien af this.state.name. Vi har bundet en funktion til tekstfeltets onChange-handler. Funktionen er en ES6 fat arrow-funktion, der har adgang til det omkringliggende this. Funktionen indeholder et kald til this.setState. Når vores komponents klasse bruger extends React.Component, arver det en række metoder som setState, forceUpdate og alle React’s lifecycles.

 

Hver gang brugeren skriver i tekstfeltet, bliver onChange handler-funktionen kaldt, handleren modtager et event, som vi kan spørge værdien af, og igennem this.setState bliver ny state sat, og der udløses en re-rendering med tekstfeltets nye værdi.

Abstraktioner i React

Vi kan introducere en stateless komponent til at wrappe vores tekstfelt. Dermed har vi skabt en abstraktion, som kan indeholde alle de forskellige HTML-input-elementer; vise en label; arbejde med konsistent stil (der kan ændres, uden at 10.000 input-felter skal opdateres rundt omkring).Det betyder også, at vi i browseren kan arbejde langt mere dynamisk med dato-inputs, ved at benytte os af open source libraries som Flatpickr.

const Input = ({type, value, onChange, label}) = {


switch (type) {

case "input":

return (

<React.Fragment>

<label>{label}</label>

<input type="text"
value={value}
onChange={onChange} />

</React.Fragment>
)
}
}

class App extends React.Component {

constructor() {

super()

this.state = {name:"Ditlev"}

}


render() {

return (

<div>

<Input type="text"
value={this.state.name}
label={"Skriv dit navn"}
onChange={(e) => this.setState({name:e.target.value})} />

</div>

)
}
}
 

Resultatet er

 

JSX og ES6

Det er næsten ikke til at komme udenom ES6 (ny version af JS) og JSX (syntaktisk sukker, der ligner HTML), når du begynder at skrive React-komponenter. Hvor det bestemt er muligt at slippe afsted med at bruge React uden at transpile JSX, så ender du med en render-metode bestående af en masse objekter, der beskriver markup – noget rod!

 

JSX er en kraftfuld abstraktion, fordi det er som at skrive HTML, men du kan embedde langt mere komplekse ting, end du kan direkte i HTML. Eksempelvis kan du med JSX behandle en arbitrær kompleks React-komponent som et HTML-tag <Newsfeed />.

ES6 udbygger JS-sproget med en masse koncepter fra andre sprog, som JS har manglet i utrolig lang tid. Se mange af disse koncepter her.

Kom i gang med React uden at blive fældet af JS

Desværre er der stadig udfordringer, før du er i stand til at skrive effektivt JS og React. Webpack og andre komplekse build tools skræmmer de fleste væk. Heldigvis har Facebook, som et led i deres developer adoption-strategi, lanceret Create React App, der gør det muligt at; “Set up a modern web app by running one command.”

De har skrevet et komplet udvikler-setup med React/Babel/Webpack, som Facebook forsat forbedrer. Det er et rigtig godt udgangspunkt for at komme i gang og kan overtages og tweakes ved at “ejecte”. Det er en lækker pakke med alt fra kode linting; dev-web-server; produktionsscripts til at bygge et JS-bundle, alt der skal gøres, når koden er klar, er at kører kommando’en npm run build, så er projektet klar til deploye (hvis alt går vel).

Pakken installeres via NPM og kan bruges overalt på computeren til at skabe nye React-projekter til prototyping, test, eller nye dele af produktionskoden.

npm install -G create-react-app

 

create-react-app MinApp

State og kompleksitet

Muligheden for at indsætte komponenter i andre komponenter giver frihed til at bygge fede applikationer. Dog bliver den frihed hurtigt begrænset, hvis du begynder at sætte en masse state rundt omkring i forskellige komponenter. Bliver applikationen tilstrækkelig kompleks, er der behov for at introducere state management for at kunne holde styr på den del.

 

I mange frontend-applikationer opstår kompleksiteten, når vi introducerer brugerautorisation. hvorved der er tilstande med afhængighed til andre tilstande. Er brugeren logget ind eller ej?

Et andet sted, hvor der opstår komplikationer med tilstanden, er, hvis vores applikation er en Single-Page Application. Det vil sige, at hver gang brugeren trykker på et link, hentes der ikke en ny side fra serveren, i stedet bliver dette håndteret af frontenden via manipulation af Window.location – enten direkte, eller via libraries som React-Router. Det betyder, at vi pludselig skal tage stilling til, hvordan tilstand opstår, hvis en bruger besøger en specifik URL eks. https://web.site/post/123/comment/456 Her skal vi på baggrund af URL’en, hente en post-resource med id 123 og vise en kommentar på denne resource med id 456.

Det mest kendte library til håndtering af state er Redux. Redux er baseret på Flux-arkitekturen og er callback-baseret. Der er også andre libraries baseret på forskellige metoder. Et af dem er MobX, som er Observable-baseret)

Redux

Redux bygger på ideen om at formulere state som handlinger i applikationen, hvor resultatet bliver reduceret og gemt i en “store”. State ligger dermed udenfor React-applikationen og bliver bundet sammen på runtime. Dette gør Redux elegant med et enkelte wrapper-kald, men det underliggende princip er, at når en komponent bliver forbundet, bliver der registreret en subscriber-funktion. Når state ændrer sig, som et resultat af en handling, bliver subscriber-funktionen kaldt, og der sker en re-rendering af komponenten med den nye state.

Arkitekturen bag Redux

Der er mange måder at håndtere state på. Ulempen ved Redux er den relative store mængde boilerplate, der skal skrives.

 

Det er op til det enkelte projekt at vurdere, hvordan state håndteres. Det kan kun betale sig at finde eller skrive noget, der løser problemet, og som er åben for udbyggelse, uden det underliggende princip ændrer sig.

Tænk i abstraktioner og designsystemer med React

Designsystem kan være et tomt buzzword. I forbindelse med React kan designsystemer ses som et sæt af generiske komponenter (som Input eksemplet), der bliver brugt om og om igen – og med rig mulighed for at ændre det underliggende uden at skulle ændre det 1000 steder. Disse komponenter kan blive enormt store, men de vil altid overholde deres simple interface og dermed gøre det nemt at flytte dem rundt og bruge dem i mange sammenhænge.

Der er også andre libraries, som Vue, Preact og Angular-components, der arbejder med komponenter. Hvad, du vælger, er op til hvilket miljø, der ønskes adgang til.

For mig personligt er React et godt valg, som giver adgang til et stort miljø af spørgsmål og svar, færdiglavede kvalitetskomponenter, som kan installeres direkte i nye projekter via NPM og opbakningen fra Facebook (især efter de ændrede React-license fra BSD-3 clause – hvor Facebook havde alt for meget magt – til MIT-license.)

Prøv React hurtigt i browseren

God kodning!