Sådan fungerer React under emhætten

React er et meget populært JavaScript-bibliotek. Med over 5,5 millioner downloads pr. Uge nyder React stor popularitet. Men ikke mange React-udviklere ved, hvordan React fungerer under emhætten.

I dette indlæg vil jeg forsøge at afdække nogle interessante ting om React, som du som React-udvikler måske finder fascinerende. Lad os starte i starten.

Men inden du starter, hvis du er en React-udvikler, har jeg nogle spændende nyheder til dig! Når du har gennemført denne artikel, vil du udvikle noget cool med React og vinde priser på vejen :)

Hvad gør React?

I sin kerne opretholder React dybest set et træ til dig. Dette træ er i stand til at udføre effektive diff-beregninger på noderne.

Tænk på din HTML-kode som et træ. Faktisk er det nøjagtigt, hvordan browseren behandler din DOM (din gengivne HTML i browseren). React giver dig mulighed for effektivt at rekonstruere din DOM i JavaScript og kun skubbe de ændringer til DOM, som faktisk er sket.

JSX er syntaktisk sukker

Der er intet som JSX - hverken til JavaScript eller til browseren. JSX er simpelthen syntaktisk sukker til oprettelse af meget specifikke JavaScript-objekter.

Når du skriver noget som:

const tag = 

Hello

hvad du i det væsentlige laver er dette:

const tag = React.createElement("h1", {}, "Hello")

Ser du, når du begynder at skrive indlejrede ting, er det ikke kun vanskeligt at kode, men det bliver også meget ubelejligt at opretholde en sådan kodebase. JSX hjælper dig dermed med at bringe HTML-renheden til JavaScript.

Men hvad gør React.createElement sig selv? Det opretter et almindeligt gammelt JavaScript-objekt. Faktisk kan du manuelt kalde det og se selv!

Ser du, vi har et objekt som dette:

{ $$typeof: Symbol(react.element), key: null, props: {children: "Hello"}, ref: null, type: "div" }

Og hvis vi begynder at indlejre elementer som dette:

React.createElement('div', { }, React.createElement('p', {}, 'A p inside a div') ) 

Vi begynder at få indlejrede genstande:

Så nu ved du, når alle JSX er parset, og alle React.createElement-opkald er løst, lander vi med et kæmpe indlejret objekt som ovenfor.

Reager gengiveren

Hvis du går tilbage til det punkt, hvor vi starter vores app, vil du se, at i din index.js-fil vil du finde følgende linje:

// .. prev code ReactDOM.render(, container)

Ovenfra ved vi, at når dette er blevet analyseret, er dette bare et stort objekt af React-elementer. Hvordan er React så i stand til at konstruere faktiske divs og p-tags ud af det? Mød ReactDOM.

ReactDOM skaber igen rekursivt noder afhængigt af deres 'type' egenskab og tilføjer dem endelig til DOM.

Det skal være klart på dette tidspunkt, at hvorfor afkobling af React fra rendererne faktisk er et godt skridt! Hvad React gør er, bare konstruere et træ af brugergrænsefladen, som ikke kun kan bruges på nettet, men også i miljøer som mobile, forudsat at en renderer er tilgængelig, som er i stand til at kommunikere med værts-OS. Her kommer React Native til at spille. Ser du, React Native bruger React-biblioteket, men ikke ReactDOM som gengivelsen. I stedet er selve pakken react-native en renderer.

Vi gør dette i en reagerende native applikation for at starte appen:

const { AppRegistry } = require('react-native') AppRegistry.registerComponent('app', () => MainComponent)

Se! Ingen ReactDOM. Hvorfor ikke? Fordi vi ikke har metoder som appendChild, har vi heller ikke et DOM-lignende miljø. I stedet for mobiltelefoner har vi brug for support til UI direkte fra OS. Men React-biblioteket behøver ikke at vide det, rendereren (React Native) tager sig af det.

Reager forsoning

Når vi siger, at React opretholder en kopi af DOM ved hjælp af virtuel DOM i JavaScript, og den bruger til at differe den til eventuelle ændringer og anvende den på ægte DOM, vil vi ikke have, at React brute-force sin måde. Reagerer, gør faktisk meget doven forsoning. Reager ville gøre det mindst mulige antal ændringer, dvs. det ville forsøge at genbruge elementer, attributter og endda stilarter, hvis det er muligt!

Overvej dette eksempel:

stuff

Lad os sige, at du ændrer dette JSX-udtryk til nedenstående ved hjælp af en eller anden tilstand:

something else

Nu mens det adskiller sig, ville React se det godt, img-tag bruger det samme className både i gamle og nye træer, så hvorfor ændre det. Og det ville bare ændre din alt-attribut og gå videre.

Der er dog en fangst. Fordi vi ikke ønsker, at React skal foretage en masse beregning på forskellige måder, antager React, at hvis en forælder har ændret sig, er dens indeholdende undertræ definitivt ændret. For eksempel:

I did not change

Hvis du ændrer denne JSX til nedenstående ved hjælp af tilstand / tilstand:

I did not change

Selvom du kunne se, at vi ikke behøver at genskabe det indre p-tag, men React har ingen måde at vide, at mens du krydser træet fra toppen (medmindre du selvfølgelig udfører kraftige træforskelle, hvilket er meget dyre algoritmer end den heuristiske O (n) reagerer følger for forskel). Så React beslutter at ødelægge alle børn (dvs. kalde deres oprydningsfunktioner i useEffect eller componentWillUnmount i klassebaserede komponenter) og genskabe børnene fra bunden.

Reager nøgler

Når du tilføjer / fjerner elementer i en node, ville React blot løbe over børnene i det gamle træ og børnene i det nye træ i noden og markere de steder, hvor det er nødvendigt at udføre enhver tilføjelse / fjernelse. Men dette har en ulempe uden yderligere hjælp fra udvikleren. Overvej dette eksempel:


    
  • A
  • B

Overvej, at dette ændres til nedenstående efter tilstand / tilstand:


   
  • Z
  • A
  • B

    Nu, når React ville begynde at sammenligne de to lister for forskel, ville det finde forskellen ved barneknude 1, ville mutere den gamle A til nye Z, derefter igen ved barneknude 2, ville mutere den fra den gamle B til nye A, og derefter til sidst tilføje den nye B-node.

    En bedre måde ville imidlertid have været at bevare de eksisterende A- og B-knudepunkter og bare forberede Z-noden. Men hvordan ville React vide om det? Reaktionstaster ville hjælpe.

    Taster giver bare en god måde at reagere på for at vide, hvilke elementer der har ændret sig eller ikke har ændret sig, mens de adskiller sig. I stedet for at sammenligne hele elementet sammenligner React nu nøglerne til børnene for at se, hvilket element der skal tilføjes / fjernes. Nedenstående måde er en effektiv måde at udføre den samme ting på:

    
        
    • A
    • B

    Hvis dette nu ændres til:

    
        
    • Z
    • A
    • B

    React ville nu vide, at nøglerne 'A' og 'B' allerede findes, så vi skal bare tilføje det nye element med nøglen 'Z'.

    Er du en React-udvikler? Vis dine React-færdigheder ved at udvikle et interaktivt spil på 3 minutter i React, og vind hættetrøjer, skjorter og kaffekrus ! Deltag i codecomp ved at slutte dig til codedamns diskordserver her

    Så dette var nogle vigtige begreber, som jeg tror ville være virkelig nyttige for dig som React-udviklere at begynde at forstå kernen i React, og hvordan det rent faktisk fungerer. Du er velkommen til at videregive eventuelle forslag eller spørgsmål, du har om det samme.

    Du kan følge mig på twitter for flere JS / kodende tweets og ting. Fred!