Les 1: Functiecomponenten

Tijdens deze bekijken we hoe een React app aangemaakt kan worden, hoe de mappenstructuur van een React app in elkaar zit en hoe we eenvoudige componenten kunnen bouwen en gebruiken.

JSX

React heeft ervoor gekozen om JavaScript en HTML te combineren, een zogeheten component combineert markup en JavaScript in één klein stukje code dat één bepaalde UI functie implementeert. Klassieke JavaScript bied geen bijzonder goede ondersteuning voor het schrijven van HTML code, hiervoor zijn een hele hoop string concatenaties nodig. Dit heeft trage en moeilijk te lezen code als gevolg.

Om dit probleem te overwinnen en toch JavaScript en HTML te combineren heeft React een uitbreiding ontwikkeld voor JavaScript. JavaScript XML (JSX), laat toe om HTML code in JavaScript te gebruiken zonder quotes of concatenaties. Het is natuurlijk onmogelijk voor een browser om zo'n code te lezen en uit te voeren. Daarom moet elke lijn JSX code gecompileerd worden naar klassiek JavaScript code.

const element = <h1>Hello, world!</h1>;
1

wordt via Babelopen in new window gecompileerd naar

const element = /*#__PURE__*/React.createElement("h1", null, "Hello, world!");
1

Babel Try it outopen in new window

Syntax regels

JSX is een geweldige uitbreiding op javaScript, maar er zijn enkele belangrijke syntax regels waarmee rekening gehouden moet worden.

De geldige HTML code

<h1>Hello World!</h1>
<h1>Hello Universe!</h1>
1
2

kan niet zomaar aan een variabele toegekend worden in JSX. De code

const element = <h1>Hello World!</h1>
<h1>Hello Universe!</h1>;
1
2

Babel Try it outopen in new window

produceert de foutmelding:

Adjacent JSX elements must be wrapped in an enclosing tag.

Dit is een gevolg van het integreren van HTML in JavaScript (en de bijhorende syntax regels). Zoals de foutmelding zegt, moeten 2 opeenvolgende JSX elementen binnen een ander element geplaatst worden. In welk element de HTML-code geplaatst wordt speelt geen rol, dit kan een <div>, <span>, ... zijn.

const element = <div>
    <h1>Hello World!</h1>
    <h1>Hello Universe!</h1>
</div>;
1
2
3
4

Bovenstaande code werkt, maar misschien werk je liever met perfect uitgelijnde code? In dat geval omring je de volledige code met ronde haken.

const element = (
    <div>
        <h1>Hello World!</h1>
        <h1>Hello Universe!</h1>
    </div>
);
1
2
3
4
5
6

Bovenstaande voorbeelden zijn relatief beperkt, we maken eigenlijk geen gebruik van JavaScript, alles wat er gebeurt zou perfect met klassieke HTML kunnen. JSX wordt pas echt interessant als we JavaScript code integreren in HTML code. We kunnen JavaScript code gebruiken door deze te omringen met accolades. Boven- en onderstaande code produceren net hetzelfde resultaat, maar de onderstaande code is dynamischer, de tekst "World" en "Universe" komen nu uit een JavaScript object.

Merk op dat alle geldige JavaScript code gebruikt kan worden tussen de accolades, in de eerste titel maken we gebruik van string concatenatie. De code tussen de accolades kan eveneens een functie zijn die een string teruggeeft.

const greeting = {
    greeting1: "World",
    greeting2: "Universe"
}

const element = (
    <div>
        <h1>Hello {greeting.greeting1 + "!"}</h1>;
        <h1>Hello {greeting.greeting2}!</h1>
    </div>
)
1
2
3
4
5
6
7
8
9
10
11

Project Aanmaken

Een nieuw React project wordt aangemaakt via het commando npx create-react-app projectNaam, waar projectNaam logischerwijs vervangen wordt met de naam van het nieuwe project.

Dit commando produceert een nieuwe map projectNaam die het nieuwe React project bevat. Deze map wordt aangemaakt als submap van de locatie waar het commando uitgevoerd wordt. Als de terminal zich, bijvoorbeeld, bevind in c:\projects, dan zal het commando npx create-react-app voorbeeld-project een nieuwe map c:\projects\voorbeeld-project aanmaken.

Tijdens het installatieproces zal je gevraagd worden of je het pakket create-react-app wil installeren, druk op enter om hiermee akkoord te gaan. Vervolgens start npm met de installatie van de nodige pakketten, dit kan even duren, zeker als je op een HDD werkt of in een map die met de cloud gesynchroniseerd wordt.

Eventueel kan je, als je WebStorm gebruikt, ook een project aanmaken door via de menubalk voor File > New > Project te kiezen. Vervolgens selecteer je een React App. Het gemarkeerde deel van de Location optie stelt de naam van het project voor. Merk op dat ook hier het npx create-react-app commando uitgevoerd wordt. Het is beter om met een terminal te leren werken dan te vertrouwen op een IDE zoals WebStorm, niet elke IDE heeft deze optie.

Fig 1: React project aanmaken via WebStorm

Mappenstructuur

De mappenstructuur van een React project is relatief eenvoudig. Hieronder bespreken we elke map en elk bestand.

Fig 2: React mappenstructuur

node_modules

De node_modules map bevat alle bibliotheken en tools die nodig zijn om een React applicatie te ontwikkelen en deployen. Daarnaast komen ook alle extra pakketten die jij, als ontwikkelaar, installeert in deze map te staan. De node_modules worden snel zeer groot, voor een basis React app zonder extra bibliotheken, is deze map al groter dan 200MB. Als je code upload op Canvas, doorstuurt om antwoord te krijgen op vraag, in een git repository plaatst, ... dan is deze map overbodig. Iedereen die de rest van je applicatie heeft, kan de node_modules dupliceren.

public

De map public bevat statische resources die niet mee gecompileerd, gebundeld en minified moeten worden. Deze map bevat een HTML-pagina index.html, dit is de enige pure HTML-code die we gebruiken in een React project. Binnen deze HTML-pagina mag enkel de inhoud van het <head> tag aangepast worden. De body van deze pagina wordt door React ingevuld.

src

Deze map bevat de eigenlijke code van de React applicatie, standaard bevat deze map een hele reeks bestanden. We vertrekken elke les van een leeg project, de inhoud van de src map mag je (voorlopig) dus weggooien als je een nieuw project maakt.

.gitignore

Elk React project wordt standaar geïnitialiseerd als een git project. De .gitignore file bevat een opsomming van de bestanden die niet in version control geplaatst mogen worden, bijvoorbeeld de map node_modules.

package.json & package-lock.json

Binnen package.json worden alle geïnstalleerde pakketten opgesomd. Hiervoor worden 2 attributen gebruikt binnen het json object. Het eerste attribuut dependencies bevat een lijst van alle geïnstalleerde pakketten die relevant zijn voor de eindgebruiker. Het tweede attribuut devDependencies bevat een lijst van alle geïnstalleerde pakketten die enkel relevant zijn tijdens de ontwikkeling van de applicatie. Zaken zoals linters, transpilers, build-tools, en testing libraries, horen hier thuis. Tijdens het compilatieproces worden enkel de dependencies gekopieerd naar de productie-build. De devDependencies worden hierbij genegeerd.

Hint

Voeg de node_modules map niet toe aan je git repository. Deze map is zeer groot en kan eenvoudig gereproduceerd worden met behulp van package.json. Dit kan met het commando

npm install
1

README.md

De readme file bevat standaard een opsomming van de commando's die nodig zijn om een React applicatie te ontwikkelen, testen, en deployen.

Componenten

React applicaties delen de UI op in kleine stukken of componenten. Dit gebeurt van bovenaf, naar onderaan. De bovenste component stelt een pagina voor, deze pagina bevat kleinere componenten die bijvoorbeeld een navigatiebalk, side-menu, en content component bevatten. De navigatiebalk is op zijn beurt ingedeeld in een titel component, navigatie component en login-form component. Deze componenten kunnen op hun beurt weer ingedeeld worden in nog kleinere componenten. Onderstaande figuur illustreert dit, de stippellijnen stellen de grenzen van een component voor.

Fig 3: React Componenten

Het doel van componenten is een herbruikbare UI, onderhoudbare UI. Elke component staat op zich en kan in de rest van de website, of op een andere website, herbruikt worden. React onderscheid twee soorten componenten, functie componenten en klasse componenten. Het grootste verschil tussen de twee is dat een functiecomponent geen data (bijvoorbeeld formulierdata) bewaren, functie componenten zijn (origineel) enkel bedoeld voor visuele weergaven. Klasse componenten bewaren wel data en kunnen reageren op acties van een gebruiker (click events, change event, keypress events, ...). Deze les blijven we bij functiecomponenten.

Een component is opgebouwd uit elementen, dit is niets anders dan één JSX-expressie, zo is

<h1>Hello World!</h1>
1

een element.

Concept: Component

Een component is een onderdeel van een React applicatie, één applicatie bestaat uit tientallen componenten. Een component staat op zich, kan herbruikt worden en gebruikt eventueel andere componenten.

Renderen

Zoals eerder gezegd, bestaat de index.html pagina, die zich in de public map bevind, uit zeer weinig code. De body bevat een noscript tag en een div. Het eerste element wordt gebruikt indien de bezoeker JavaScript gedeactiveerd heeft. Het tweede element vormt de kern van de applicatie. Alle componenten zullen hierin geplaatst worden door React.

/public/index.html
<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
</body>


 

1
2
3
4

Net zoals er voor een statische website steeds een index.html nodig is, moeten we voor een React website ook steeds een index.js toevoegen. Dit doen we in de src map. In dit bestand leggen we de link met public/index.html. De div kan eenvoudig opgehaald worden via de standaard JavaScript methode document.getElementById.

/src/index.js
const rootElement = document.getElementById("root");
1

Om vervolgens een React component te tonen moet de React method render gebruikt worden. Deze methode is beschikbaar in de module react-dom. De render methode heeft twee parameters. De eerste parameter is het element of de component die gerenderd moet worden, de tweede parameter is het HTML-element waarin gerenderd moet worden.

/src/index.js
// Importeren van "react-dom", de bibliotheek die het renderen mogelijk maakt.
import ReactDOM from "react-dom";

// Ophalen van het root element uit public/index.html
const rootElement = document.getElementById("root");

ReactDOM.render(
    <h1>Hello World!</h1>,    // Het element dat gerenderd wordt.
    rootElement               // Het root element waarin gerenderd moet worden.         
);
1
2
3
4
5
6
7
8
9
10

CodeSandboxopen in new window

Bovenstaande code produceert een pagina waarop de tekst "Hello World!" getoond wordt, via de CodeSandboxopen in new window link kan de code en het resultaat bekeken worden.

Fig 4: Hello World! in React

Functie componenten

Een React component is, zoals hierboven gezegd, een klein onderdeel van een webapplicatie. Om een functie component te definiëren, gebruiken we, een JavaScript functie. De enige vereiste voor deze functie is dat de returnwaarde een JSX-expressie is. Bovenstaand voorbeeld kan eenvoudig als een component geschreven worden, dit betekent dat ook de render code aangepast moet worden zodat de nieuwe component gebruikt wordt.

Via de CodeSandbox links kan het resultaat van de voorbeelden bekeken worden.

/src/index.js
const HelloWorld = () => {
    return <h1>Hello World!</h1>;
}

ReactDOM.render(
    <HelloWorld/>,                // De component die gerenderd wordt.
    // <HelloWorld><HelloWorld/>, // Equivalente manier om de component te renderen.
    rootElement                   // Het root element waarin gerenderd moet worden.         
);
1
2
3
4
5
6
7
8
9

CodeSandboxopen in new window

Concept: Function component

Een functie component is een functie die één herbruikbaar onderdeel van de user interface definieert en JSX-code teruggeeft. De naam van zo'n functie begint steeds met een hoofdletter. Een functie component kan ergens anders in de code gebruikt worden als een HTML element.

const FunctionComponent = () => {
    return <p>This is a function component,
        the return value must be JSX code.
    </p>
}

const exampleUsage = <FunctionComponent/>;
1
2
3
4
5
6
7

Properties

Stel we willen een lijst van van enkele belangrijke grondleggers van de computerwetenschappen renderen. De eenvoudigste optie is natuurlijk via een component waar al deze personen expliciet uitgeschreven worden.

/src/index.js
const ComputerScientistList = () => {
    return <div>
        <h1>Famous computer scientists</h1>
        <ul>
            <li>
                Charles Babbage (1791 - 1871): Originated the concept of a programmable general-purpose computer.
                Designed the Analytical Engine and built a prototype for a less powerful mechanical calculator.
            </li>
            <li>
                Ada Lovelace (1815 - 1852): An English mathematician and writer, chiefly known for her work on Charles
                Babbage's proposed mechanical general-purpose computer, the Analytical Engine. She was the first to
                recognize that the machine had applications beyond pure calculation, and created the first algorithm
                intended to be carried out by such a machine. As a result, she is often regarded as the first to
                recognize the full potential of a "computing machine" and the first computer programmer.
            </li>
            <li>
                Alan Turing (1912 - 1954): Made several fundamental contributions to theoretical computer science,
                including the Turing machine computational model, the conceiving of the stored program concept and the
                designing of the high-speed ACE design. Independently of Alonzo Church, he formulated the Church-Turing
                thesis and proved that first-order logic is undecidable. He also explored the philosophical issues
                concerning artificial intelligence, proposing what is now known as Turing test.
            </li>
        </ul>
    </div>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

CodeSandboxopen in new window

Dit is echter helemaal niet efficient, elk element in de lijst heeft dezelfde structuur, zodra iets meerdere keren voorkomt in de applicatie is het best hier een aparte component van te maken.

We kunnen eenvoudig 3 componenten maken, één voor elk van 3 computerwetenschappers, dit is natuurlijk niet veel beter. Een component moet herbruikbaar zijn, het is dus nodig om de naam en voornaam, het geboorte- en sterftejaar, en de bijdragen door te geven aan de nieuwe component. Hiervoor kunnen we de properties gebruiken.

We definiëren een nieuwe component ComputerScientist die de eigenschappen van één bekende computerwetenschapper doorgegeven krijgt via de properties.

/src/index.js
const ComputerScientist = (props) => {
    return <li>
        {props.firstName} {props.lastName} ({props.birth} - {props.death}):
        <p>{props.accomplishments}</p>
    </li>;
}
1
2
3
4
5
6

Deze component kan vervolgens gebruikt worden in de component ComputerScientistList

/src/index.js
const ComputerScientistList = () => {
    return <div>
        <h1>Famous computer scientists</h1>
        <ul>
            <ComputerScientist
                firstName={"Charles"} lastName={"Babbage"}
                birth={1791} death={1871}
                accomplishments={"Originated the concept of a programmable general-purpose computer. Designed the Analytical Engine and built a prototype for a less powerful mechanical calculator. "}
            />

            <ComputerScientist
                firstName={"Ada"} lastName={"Lovelace"}
                birth={1814} death={1852}
                accomplishments={"An English mathematician and writer, chiefly known for her work on Charles Babbage's proposed mechanical general-purpose computer, the Analytical Engine. She was the first to recognize that the machine had applications beyond pure calculation, and created the first algorithm intended to be carried out by such a machine. As a result, she is often regarded as the first to recognize the full potential of a \"computing machine\" and the first computer programmer."}
            />

            <ComputerScientist
                firstName={"Alan"} lastName={"Turing"}
                birth={1912} death={1954}
                accomplishments={"Made several fundamental contributions to theoretical computer science, including the Turing machine computational model, the conceiving of the stored program concept and the designing of the high-speed ACE design. Independently of Alonzo Church, he formulated the Church-Turing thesis and proved that first-order logic is undecidable. He also explored the philosophical issues concerning artificial intelligence, proposing what is now known as Turing test."}
            />
        </ul>
    </div>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

CodeSandboxopen in new window

Concept: Properties

De properties of props zijn beschikbaar op elke component. Voor functie componenten worden de properties meegegeven via een parameter props in de functie die de component definieert. Deze parameter is steeds een JavaScript object. In JSX-code kunnen properties doorgegeven worden als HTML-attributen.

const FunctionComponent = (props) => {
    return <p>{props.example}</p>;
}

const exampleUse = <FunctionComponent
    example={"This is an example value for the property example."}/>
1
2
3
4
5
6

Lussen in JSX

In de meeste gevallen zal data, zoals de computerwetenschappers, geladen worden vanuit een API of database, en bewaard worden in een array.

Lijst van computerwetenschappers in JSON-formaat
const computerScientists = [
    {
        firstName: "Charles",
        lastName: "Babbage",
        birth: 1791,
        death: 1871,
        accomplishments: "Originated the concept of a programmable general-purpose computer. Designed the Analytical Engine and built a prototype for a less powerful mechanical calculator. "
    },
    {
        firstName: "Ada",
        lastName: "Lovelace",
        birth: 1814,
        death: 1852,
        accomplishments: "An English mathematician and writer, chiefly known for her work on Charles Babbage's proposed mechanical general-purpose computer, the Analytical Engine. She was the first to recognize that the machine had applications beyond pure calculation, and created the first algorithm intended to be carried out by such a machine. As a result, she is often regarded as the first to recognize the full potential of a \"computing machine\" and the first computer programmer."
    },
    {
        firstName: "Alan",
        lastName: "Turing",
        birth: 1912,
        death: 1954,
        accomplishments: "Made several fundamental contributions to theoretical computer science, including the Turing machine computational model, the conceiving of the stored program concept and the designing of the high-speed ACE design. Independently of Alonzo Church, he formulated the Church-Turing thesis and proved that first-order logic is undecidable. He also explored the philosophical issues concerning artificial intelligence, proposing what is now known as Turing test."
    }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Via een lus kunnen we door deze array itereren en de nodige componenten aanmaken, let op, dit moet gebeuren voor het return keyword. Elk van de nieuwe componenten moet bewaard worden in een nieuwe array die we dan kunnen uitprinten in de JSX-code die teruggegeven wordt.

/src/index.js
const ComputerScientistList = () => {

    const output = []

    for (const scientist of computerScientists) {
        output.push(
            <ComputerScientist
                firstName={scientist.firstName} lastName={scientist.lastName}
                birth={scientist.birth} death={scientist.death}
                accomplishments={scientist.accomplishments}/>
        )
    }

    return <div>
        <h1>Famous computer scientists</h1>
        <ul>
            {output}
        </ul>
    </div>;
}




 
 
 
 
 
 
 
 




 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

CodeSandboxopen in new window

Bovenstaande code kan nog heel wat duidelijker geschreven worden. De spread operator (...) kopieert alle eigenschappen van een object en behoud dezelfde naam. Dus produceren

/src/index.js
for (const scientist of computerScientists) {
    output.push(
        <ComputerScientist
            firstName={scientist.firstName} lastName={scientist.lastName}
            birth={scientist.birth} death={scientist.death}
            accomplishments={scientist.accomplishments}
        />)
}
1
2
3
4
5
6
7
8

en

/src/index.js
for (const scientist of computerScientists) {
    output.push(<ComputerScientist {...scientist}/>);
}
1
2
3

CodeSandboxopen in new window

exact hetzelfde resultaat.

props.children

Elke functiecomponent kan gebruikt worden als zelfsluitend HTML-element. Dit is niet altijd voldoende, in sommige gevallen is een het nodig om kinderen te definiëren voor een functiecomponent.

Stel, we willen een lijst van letters uitprinten, elke letter krijgt dezelfde opmaak. De component Letter zorgt dus enkel voor de opmaak van de letter en voegt verder niets toe. Als de hoeveelheid kinderen van zo'n component groot wordt, is het onmogelijk om alles via standaard properties door te geven en overzichtelijke en leesbare code te schrijven. Het children property dat aanwezig is op elke component bied hiervoor een oplossing.

/src/index.js
const Letter = (props) => {
    return <div>
        {props.children} {/* Render de kinderen van deze component.*/}
    </div>;
}

ReactDOM.render(
    <div>
        <Letter>A</Letter> {/* A is een kind van de component Letter*/}
        <Letter>E</Letter>
        <Letter>I</Letter>
        <Letter>O</Letter>
        <Letter>U</Letter>
    </div>,
    rootElement
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

CodeSandboxopen in new window

Als we Letter schrijven zonder props.children werkt de code niet en wordt er niets getoond.

CSS

CSS op een aantal verschillende manieren toegevoegd worden aan een React applicatie. CSS kan toegevoegd worden via een stylesheet, in JavaScript of via een framework zoals Bootstrap. Vanaf les 3 maken we gebruik van een framework.

CSS via stylesheets

De eerste optie is de meest eenvoudige, en is bekend bij elke webdeveloper. Stylesheets kunnen in de public map geplaatst worden en via een klassiek <link> tag gekoppeld worden aan index.html.

We kunnen bijvoorbeeld een bestand index.css toevoegen aan de public map.

.letter {
    padding: 10px;
    margin: 10px;
    background-color: #ffde00;
    color: #333;
    display: inline-block;
    font-family: monospace;
    font-size: 32px;
    text-align: center;
}
1
2
3
4
5
6
7
8
9
10

Vervolgens kan dit bestand eenvoudig gelinkt worden in public/index.html.

/src/index.js
<head> 
   <!-- Niet relevante delen weggelaten.-->
   <link rel="stylesheet" href="index.css">
</head>


 

1
2
3
4

De CSS-code verwacht een klasse, deze toevoegen aan de component Letter is niet bijzonder moeilijk. Het is wel belangrijk om op te merken dat we attribuut class niet kunnen gebruiken, dit is namelijk een keyword in JavaScript. React gebruikt het attribuut className om een CSS-klasse mee te geven in JSX-code.

/src/index.js
const Letter = (props) => {
    return <div className="letter">
        {props.children}
    </div>;
}

 



1
2
3
4
5

CodeSandboxopen in new window

Een alternatieve manier om de CSS mee te geven is deze toe te voegen in index.js, CSS-bestanden kunnen geïmporteerd worden in een JavaScript file. Dit heeft één belangrijk voordeel ten opzichte van de vorige optie. CSS die in JavaScript geïmporteerd wordt zal, tijdens het bouwen van een productie build, mee geoptimaliseerd worden. Ongebruikte klassen worden zo verwijderd en het CSS-bestand wordt geminimaliseerd (alle overtollige spaties en newlines worden weggehaald).

/src/index.js
import "./index.css";
1

CodeSandboxopen in new window

CSS in JavaScript

Het HTML-attribuut style kan gebruikt worden om inline CSS toe te voegen, in React kan dit ook. Het enige verschil is we in JSX-code gebruik kunnen maken van JavaScript objecten om de stijl toe te voegen, in de plaats van een ;-seperated string in HTML. Een belangrijke opmerking is dat CSS eigenschappen niet rechtstreeks vertaald kunnen worden naar JavaScript. Een attribuut als font-family wordt fontFamily, background-color wordt backgroundColor, ... Omdat de CSS in de componenten geschreven is, kunnen properties gebruikt worden om bepaalde eigenschappen te overschrijven.

/src/index.js
const Letter = (props) => {
    const letterStyle = {
        padding: 10,
        margin: 10,
        backgroundColor: props.bgcolor || "#ffde00",
        color: "#333",
        display: "inline-block",
        fontFamily: "monospace",
        fontSize: 32,
        textAlign: "center"
    };

    return <p style={letterStyle}>{props.children}</p>
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

CodeSandboxopen in new window

Import & Export

Alle componenten in één bestand bewaren zorgt snel voor onnodig grote en slecht onderhoudbare code. We zonderen componenten af in individuele bestanden.

We plaatsen de component Letter in een apart bestand letter.js. Voordat de component gebruikt kan worden in andere bestanden moet deze geëxporteerd worden. Dit kan via het export keyword.

/src/letter.js
const Letter = (props) => {
    return <p>{props.children}</p>
};

export {Letter};




 
1
2
3
4
5

Vervolgens kunnen we de component importeren en gebruiken in index.js.

/src/index.js
import ReactDOM from "react-dom";
import {Letter} from "./letter";

const rootElement = document.getElementById("root");

ReactDOM.render(
  <div>
      <Letter bgcolor="#58B3FF">A</Letter>
      <Letter bgcolor="#FFD52E">I</Letter>
      <Letter bgcolor="#49DD8E">O</Letter>
      <Letter>U</Letter>
  </div>,
  rootElement                          
);

 












1
2
3
4
5
6
7
8
9
10
11
12
13
14

CodeSandboxopen in new window

Last Updated:
Contributors: Sebastiaan Henau, Kilian Fastenakels