Les 4: Lifecycle & Container Components

Tijdens deze les bekijken we hoe we in een klassieke React applicatie (class components) de componenten het best kunnen opsplitsen om de herbruikbaarheid te optimaliseren. Vervolgens bekijken we de lifecycle van een React applicatie, en hoe we de verschillende lifecycle methodes kunnen gebruiken om de applicatie te optimaliseren en correct te laten werken. Tenslotte bekijken we hoe een we controles kunnen toevoegen aan onze componenten, zodat we waarschuwingen te zien krijgen in de developer tools als er een property ontbreekt of een fout datatype heeft.

Startbestanden

Open Weather API

Tijdens deze les bouwen we een applicatie waarmee we de weersvoorspelling voor de komende 7 dagen kunnen bekijken. Om deze applicatie te bouwen maken we gebruik van een de Open Weather APIopen in new window. Deze API heeft een gratis tier waarmee je 1000 calls per dag kan uitvoeren. Aangezien dit niet veel is, zal je zelf een API Key moeten aanvragen om de voorbeeldcode uit te kunnen voeren. Dit kan op https://home.openweathermap.org/users/sign_upopen in new window.

Fig 1: Eindresultaat

Voor deze les zijn geen CodeSandbox voorbeelden voorzien, aangezien dit niet mogelijk is zonder de API key publiek te publiceren.

Dotenv

Een API key, een database URL, een wachtwoord en andere zaken die gebruikt worden in een applicatie, maar geen onderdeel uitmaken van de code van je website, kunnen in een .env file bewaard worden. Dit bestand wordt ingeladen tijdens het starten van je applicatie, en zo zijn de wachtwoorden, urls, en andere zaken beschikbaar in je applicatie. Deze bibliotheek kan geïnstalleerd worden met onderstaand commando.

npm install dotenv
1

Vervolgens kan je een .env file aanmaken in de root van je React project.

Fig 2: Locatie van .env

Binnen dit bestand kan je environment variables configureren, deze variables moeten steeds beginnen met REACT_APP_.

REACT_APP_OPEN_WEATHER_API_KEY=<YourApiKeyHere>

In de React applicatie kan deze environment variable ingeladen worden als door gebruikt te maken van onderstaande code.

process.env.REACT_APP_OPEN_WEATHER_API_KEY
1

Gevoelige API keys

Alhoewel wij dit bestand momenteel gebruiken om een API key te bewaren is dit niet veilig. Enkel API keys waarvoor de backend geconfigureerd is om, alle requests die niet van de domeinnaam van de applicatie komen, af te keuren, kunnen hier bewaard worden.

Als de backend geen ondersteuning bied om te filteren op basis van domeinnaam, dan moet je een eigen proxy API bouwen, die enkel door jouw website gebruikt kan worden. De communicatie verloopt dan als volgt: React app <--> eigen proxy API <--> externe API. Doe je dit niet, dan kan een kwaadwillige de API key uit de code van je website halen en deze gebruiken om data te stelen, te verwijderen of gewoon om zeer veel calls te doen, zodat je rekening groot wordt.

Ook voor zo'n proxy api kan .env gebruikt worden als deze API geschreven is in Node.js.

Axios

Om te communiceren met de API maken we gebruik van Axiosopen in new window. Axios is een promise based HTTP client voor de browser en Node.js.

npm install axios
1

Axios bied enkele voordelen ten opzichte van de vanilla Fetch APIopen in new window. Axios stelt de gebruiker in staat op networkrequests te annuleren, daarnaast is het veel eenvoudiger om de requests aan te passen. Time-outs, authentication, proxy servers, maximum response grootte, ... zij allemaal veel eenvoudiger te configureren met behulp van Axios. Daarnaast bevat Axios ook een ingebakken functionaliteit om progress bars te bouwen. Tenslotte geeft Axios ook errors terug als een request niet uitgevoerd kon worden, terwijl de Fetch API dit niet doet.

Promises

Een promise is een belofte dat een methode ergens in de toekomst een resultaat zal teruggeven. Het belangrijkste deel van voorgaande zin is "ergens in de toekomst", de methode voert geen onmiddellijke operatie uit. Het is mogelijk dat het een minuut duurt voor het resultaat beschikbaar is. Promises zijn asynchroon, omdat de operaties even kunnen duren, is het geen goed idee om te wachten tot de operatie afgewerkt is. Dit zou betekenen dat de gebruiker, bijvoorbeeld, een halve minuut niets kan doen. Een zeer slechte user experience dus. Omwille van de asynchrone aard van een promise is het mogelijk voor de gebruikers om andere acties uit te voeren terwijl er gewacht wordt op het resultaat. Dit betekend dus dat tussen twee statements in een asynchrone functie, eventueel andere code uitgevoerd wordt. De flow van het programma is dus niet meer puur iteratief.

Een promise is een belofte dat er iets teruggegeven zal worden in de toekomst, wat dat iets juist kan zijn wordt bepaald door het type van de promise. Een promise heeft steeds de structuur Promise<T> waar T alle mogelijke datatypes kan zijn, een string, boolean, number, void, een custom type, ...

Een promise heeft een methode then die uitgevoerd wordt als de promise succesvol resolved is, i.e. als er zich geen errors hebben voorgedaan tijdens het uitvoeren van de asynchrone methode. Naast de then methode is er ook een catch methode aanwezig om te reageren op error. Onderstaande code zal de tekst "Do something with the result" uitprinten.

const someAsynchronousOperation = async () => {
    return "Result"
}

const callSomeAsynchronousOperation = () => {
    someAsynchronousOperation()
        .then(result => console.log("Do something with the result."))
        .catch(error => console.error("An error occurred."));
}

callSomeAsynchronousOperation();
1
2
3
4
5
6
7
8
9
10
11

CodeSandboxopen in new window

Als we someAsynchronousOperation() methode aanpassen naar onderstaander code zal de tekst "An error occurred" uitgeprint worden.

const someAsynchronousOperation = async () => {
    throw new Error();
}
1
2
3

CodeSandboxopen in new window

Zoals in bovenstaande methodes te zien is, geeft een asynchrone methode steeds een Promise terug, eventueel een Promise<void> als de methode geen return waarde heeft.

De async en await keywords zijn een wrapper rond promises De callSomeAsynchronousOperation methode kan herschreven worden als een asynchrone methode op volgende manier. Merk op dat we nu een try-catch blok nodig hebben. De promise kan eventueel een error teruggeven en deze moet opgevangen worden.

const callSomeAsynchronousOperation = async () => {
    try {
        const result = await someAsynchronousOperation();
        console.log('Do something with the result.');
    } catch (error) {
        console.log("An error in the asynchronous function");
    }
}
1
2
3
4
5
6
7
8

CodeSandboxopen in new window

Promises kunnen aan elkaar gekoppeld worden, elke then methode geeft ook een promise terug

callSomeAsynchronousOperation()
    .then(r => {
        console.log('In Promise 2');
        return;
    })
    .then(r => {
        console.log('In Promise 3');
        return;
    })
1
2
3
4
5
6
7
8
9

CodeSandboxopen in new window

API Aanspreken

We beginnen met het ontwikkelen van de API, hiervoor gebruiken we klasse WeatherAPI, die in de startbestanden te vinden is. Voor we de API kunnen aanspreken moet de API key ingeladen worden, zoals eerder gezegd kan dit op onderstaande manier. We noteren de instantievariabele API_KEY in hoofdletters en snake_case omdat dit een constante is, i.e. iets wat doorheen de applicatie niet van waarde kan veranderen.

/src/apis/weatherApi.js
class WeatherAPI {
    API_KEY = process.env.REACT_APP_OPEN_WEATHER_API_KEY;
}
1
2
3

De Open Weather API is beschikbaar op "https://api.openweathermap.org/data/2.5/onecall", hier is '/onecall' het endpoint en 'https://api.openweathermap.org/data/2.5' de baseURL waaraan één of meerdere endpoints gekoppeld kunnen worden. We kunnen deze baseURL configureren in Axios, zo moet enkel het endpoint meegegeven worden met elk request.

/src/apis/weatherApi.js
class WeatherApi {

    API_KEY = process.env.REACT_APP_OPEN_WEATHER_API_KEY;

    constructor() {
        axios.defaults.baseURL = "https://api.openweathermap.org/data/2.5";
    }
}





 


1
2
3
4
5
6
7
8

In de documentatie van de one callopen in new window API, zien we onderstaand voorbeeld.

https://api.openweathermap.org/data/2.5/onecall?lat=33.44&lon=-94.04&exclude=hourly,daily&appid={API key}

We kunnen dit, als volgt, omzetten in een Axios call. De parameters worden via een JavaScript object doorgegeven. Onderstaande code kan herschreven worden zonder een try-catch, in dat geval geef je de promise van de request methode terug en gebeurt de foutafhandeling in de React componenten.

/src/apis/weatherApi.js
getWeather = async (latitude, longitude) => {
    try {
        const result = await axios
            .request({
                url: "/onecall",
                params: {
                    lat: latitude,
                    lon: longitude,
                    appid: this.API_KEY,
                    units: "metric",
                    lang: "nl"
                }
            })
        if (result.status === 200) {
            return result.data;
        }
    } catch (err) {
        console.log(err);
    }
    return undefined;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Componenten uitwerken

In de startbestanden is in de map componenten de class component WeatherList te vinden. We zien in het startbestand dat de data die uit de API komt bewaard wordt in de state van de component. Dit is natuurlijk noodzakelijk aangezien de data pas opgeroepen wordt nadat de component geladen is, zodra de data opgehaald is moet de component opnieuw gerenderd worden, maar dit keer met de weersinformatie. Ook de plaats en coördinaten staan in de state, aangezien we deze later willen kunnen aanpassen.

/src/components/weatherList.js
class WeatherList extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            weather: undefined,
            city: 'Geel',
            latitude: 51.1659867,
            longitude: 4.9160109,
        };
    }

    // Rest van de code weggelaten
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Het is best om de API calls niet uit te voeren in de constructor. Dit zou betekenen dat er extra werkt nodig is voor de render() functie opgeroepen kan worden en de gebruiker iets ziet. We willen altijd zo snel mogelijk iets tonen, al is het maar een preloader die aangeeft dat de pagina ana het laden is. Dit betekent dat de constructor zo klein mogelijk moet zijn.

Class components bevatten de componentDidMount lifecycle methode. Deze methode wordt uitgevoerd nadat de component toegevoegd is aan de DOM en gerenderd is. Dit is dan ook een ideale locatie om de eerste API call uit te voeren. Deze methode wordt slecht één keer uitgevoerd, als de component ook ondersteuning moet bieden voor het refreshen van data is het dus beter om de call nog af te zonderen in een aparte methode.

/src/components/weatherList.js
class WeatherList extends React.Component {

    // Rest van de code weggelaten

    componentDidMount = () => {
        this.retrieveWeatherData();
    }

    retrieveWeatherData = async () => {
        const api = new WeatherApi();

        const weather = await api.getWeather(this.state.latitude, this.state.longitude);

        if (weather === undefined) {
            return;
        }

        this.setState({weather});
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Container & presentational components

De huidige structuur bevat zowel data retrieval logica als presentatie logica in dezelfde component. Dit is niet ideaal. De presentatie zou losgekoppeld moeten worden van het ophalen van de data. Zou wordt het mogelijk om de data op een andere manier te presenteren, of is het mogelijk de presentatie te gebruiken met een andere databron. Een andere databron kan bijvoorbeeld gecashte, historische, data op een eigen server zijn.

Om dit probleem op te lossen wordt een klassieke, pure React applicatie, i.e. een applicatie zonder extern state management framework, meestal opgedeeld in presentational en container components. Zo verlagen we de koppeling tussen de verschillende onderdelen van de applicatie en kunnen produceren we een beter onderhoudbare applicatie.

Een container component is een component die data ophaalt, data transformeert, aan state management en weinig tot geen presentatielogica bevatten. Enkel divs die presentational components bevatten, worden gerenderd door de container component. Deze component geeft dan ook data door (via properties) aan de presentational components.

Een presentational component is (meestal) een functiecomponent, als er state aanwezig is heeft dit enkel met presentatie te maken, dus dingen als "is dit menu open of dicht" mogen, maar zaken "dit staat in het formulier" mogen niet. Omdat deze componenten enkel voor de presentatie dienen, en dus geen weet hebben vanwaar hun properties komen, kunnen de componenten eenvoudig herbruikt worden in andere projecten of op andere locaties in de website.

App omvormen volgens het presentational container patroon

De eerste stap is het verhuizen van de methode retrieveWeatherData en de state uit de WeatherList naar de WeatherListContainer component.

/src/containers/weatherListContainer.js
class WeatherListContainer extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            weather: [],
            city: 'Geel',
            latitude: 51.1659867,
            longitude: 4.9160109,
        };
    }

    componentDidMount = () => {
        this.retrieveWeatherData();
    }

    retrieveWeatherData = async () => {
        const api = new WeatherApi();

        const weather = await api.getWeather(this.state.latitude, this.state.longitude);

        if (weather === undefined) {
            return;
        }

        this.setState({weather});
    }

    // Render functie weggelaten, deze was reeds te vinden in de startbestanden.
}
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
26
27
28
29
30
31

Nu de state weg is uit de WeatherList component, kan deze component omgevormd worden tot een functiecomponent.

/src/components/weatherList.js
const WeatherList = (props) => {
    let output = [];

    for (let day of props.daily) {
        output.push((
            <Col key={day.dt} xs={12} md={3} className="d-flex align-items-stretch">
                <WeatherItem day={day} city={props.city}/>
            </Col>
        ));
    }

    return (
        <Row>
            {output}
        </Row>
    )

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

Tenslotte moeten we enkel nog index.js aanpassen zodat de container gebruikt wordt.

/src/index.js
ReactDOM.render(
    <Container>
        <WeatherListContainer/>
    </Container>,
    document.getElementById('root')
);
1
2
3
4
5
6

Lifecycle

We hebben reeds één van de 3 belangrijkste lifecycle methodes gezien, namelijk componentDidMount. De twee andere belangrijke lifecycle methodes zijn componentDidUpdate en componentWillUnmount. Naast deze twee methodes zijn er nog enkele anderen, die weinig to niet gebruikt worden, voor meer info hierover verwijzen we de geïnteresseerde lezer naar de React documentatie.open in new window.

componentDidMount

In componentDidMount voeren we API calls en andere asynchrone of kostelijke operaties uit. Zoals hierboven beschreven kunnen deze operaties niet in de constructor gebeuren, want dit is te veel extra werk waardoor het langer duurt voor de gebruiker iets te zien krijgt. Deze methode wordt één keer uitgevoerd, na de constructor en de eerste render() call.

componentWillUnmount

Elke asynchrone operatie vormt een gevaar. Het is namelijk mogelijk dat de gebruiker een actie uitvoert die de component uit de DOM verwijderd voor het resultaat van de asynchrone operatie teruggeven is. Dit veroorzaakt memory leaks, iets wat zware gevolgen kan hebben. De componentWillUnmount lifecycle methode biedt hier een oplossing voor.

Deze methode wordt uitgevoerd net voordat een component uit de DOM verwijderd wordt, bijgevolg is dit de ideale plek om alle asynchrone operaties te annuleren. Stel we breiden de WeatherAPI uit met een asynchrone methode die de API call pas uitvoert na 10 seconden, zo wordt een lange asynchrone operatie of een (zeer) traag netwerk gesimuleerd.

We voegen ook een methode getCancelTokenSource toe, die een token teruggeeft waarmee een API call geannuleerd kan worden.

/src/apis/weatherApi.js
getWeatherSlow = async (latitude, longitude, cancelTokenSource) => {
    // Wacht 5 seconden door een nieuwe Promise te maken die na 5 seconden gedaan heeft.
    await new Promise(resolve => setTimeout(resolve, 5000));
    try {
        const result = await axios
            .request({
                url: "/onecall",
                params: {
                    lat: latitude,
                    lon: longitude,
                    appid: this.API_KEY,
                    units: "metric",
                    lang: "nl"
                },
                cancelToken: cancelTokenSource.token
            })
        if (result.status === 200) {
            return result.data;
        }
    } catch (err) {
        console.log(err);
    }
    return undefined;
}

getCancelTokenSource = () => {
    const CancelToken = axios.CancelToken;
    return CancelToken.source();
}
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
26
27
28
29

We passen vervolgens de code van de WeatherListContainer aan, zodat deze nieuwe, trage, API call gebruikt wordt. Hiervoor voegen we ook 2 instantievariabelen toe, zodat we een de cancelToken kunnen meegeven als parameter aan de getWeatherSlow methode.

/src/containers/weatherListContainer.js
class WeatherListContainer extends React.Component {

    // Niet relevante en onverandere code is weggelaten.

    api = new WeatherApi();
    cancelToken = this.api.getCancelTokenSource();

    componentDidMount = () => {
        // this.retrieveWeatherData();
        this.retrieveWeatherDataSlow();
    }

    retrieveWeatherDataSlow = async () => {
        const weather = await this.api
            .getWeatherSlow(this.state.latitude, this.state.longitude, this.cancelToken);

        if (weather === undefined) {
            return;
        }

        this.setState({weather});
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Vervolgens maken we gebruik van de WeatherContainerWrapper component die deel uitmaakt van de startbestanden. Deze component doet niets anders dan een knop toevoegen waarmee de WeatherListContainer verborgen en getoond kan worden. We moeten deze enkel toevoegen aan index.js.

/src/index.js
ReactDOM.render(
    <Container>
        <WeatherContainerWrapper/>
    </Container>,
    document.getElementById('root')
);
1
2
3
4
5
6

Zoals in onderstaande GIF te zien is, genereert bovenstaande code een foutmelding, als de component uit de DOM verwijderd wordt voor de 10 seconden gepasseerd zijn. Er doet zich een memory leak voor, in ons geval is dit niet zo'n probleem, omdat de applicatie klein is en zeer weinig componenten bevat. Maar gebruik je gelijkaardige code in een grotere applicatie, met veel asynchrone operaties, dan kan dit zware gevolgen hebben voor de performance van de webapplicatie.

Fig 3: Memory Leak

Dit probleem kan eenvoudig verholpen worden door de componentWillUnmount lifecycle methode te gebruiken.

/src/containers/weatherListContainer.js
componentWillUnmount() {
        this.cancelToken.cancel("The Request has been cancelled because the component unmounted.");
}
1
2
3

Na het toevoegen van deze methode, is het memory leak opgelost. Dit is te zien in onderstaande GIF.

Fig 4: Geen Memory Leak

De componentWillUnmount lifecycle methode is niet enkel bedoeld voor API calls, ook unsubscriben van Observables (zie volgende les), of het annuleren van een setInterval of setTimeout kunnen hier gebeuren. Voor meer informatie over hoe je deze laatste 2 methodes stopt, verwijzen we de geïntereseerde lezer respectievelijk door naar MDN setIntervalopen in new window en MDN setTimeoutopen in new window.

componentDidUpdate

De componentDidUpdate wordt uitgevoerd na de render() methode. Dit betekent dat dit de ideale locatie is om de DOM rechtstreeks te manipuleren. Alhoewel dit zoveel mogelijk vermeden moet worden, zijn er situaties waar dit wel nodig is. Bijvoorbeeld in gevallen waar je moet communiceren met third party UI componenten die klassieke JavaScript gebruiken en geen React componenten aanbieden, of als je naar een bepaald element wil scrollen, ... De signatuur van de methode is als volgt

componentDidUpdate(prevProps, prevStat)
{
}
1
2
3

Dit betekent dat deze methode gebruikt kan worden om API calls uit te voeren als bepaalde state values of properties gewijzigd zijn. Dit kan nuttig zijn om het aantal API calls te optimaliseren.

Waarschuwing

Het gebruik van setState in de componentDidUpdate lifecycle methode kan een oneindige lus tot gevolg hebben. Door de setState call conditioneel te maken, i.e. te omringen met een if, kan dit probleem vermeden worden.

Gebruikt, in componentDidUpdate nooit een setState oproep zonder omringende if.

Stel we willen de temperatuur voor de komende 7 dagen niet enkel in cards weergeven, maar ook als lijngrafiek en we willen dit doen aan de hand van Chart.jsopen in new window. Deze bibliotheek bied geen React component aan, we moeten de DOM dus rechtstreeks aanspreken. Deze bibliotheek kan geïnstalleerd worden via npm.

npm install chart.js
1

We kunnen de render functie van de WeatherListContainer aanpassen zodat een canvas gerenderd wordt als de weerdata ingeladen is.

/src/containers/weatherListContainer.js
render() {
    if (this.state.weather === undefined) {
        return <></>;
    }

    return (
        <div>
            <WeatherList daily={this.state.weather.daily} current={this.state.weather.current}
                         city={this.props.city}/>
            <div className={'m-2'}>
                <canvas id="myChart" width="400" height="200"/>
            </div>
        </div>
    );
}










 




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

Vervolgens kunnen we gebruik maken van de componentDidUpdate lifecycle methode om de grafiek te tekenen.

/src/containers/weatherListContainer.js
import {Chart, LineController, CategoryScale, LinearScale, LineElement, PointElement} from 'chart.js';

class WeatherListContainer extends React.Component {

    // Niet relevante code is weggelaten.

    componentDidUpdate(prevProps, prevState) {
        const ctx = document.getElementById('myChart').getContext('2d');
        Chart.register(LineController, CategoryScale, LinearScale, LineElement, PointElement);
        new Chart(ctx, {
            type: 'line',
            data: {
                labels: this.state.weather.daily.map(d => new Date(d.dt * 1000).toLocaleDateString()),
                datasets: [{
                    data: this.state.weather.daily.map(d => d.temp.day),
                    borderWidth: 1,
                    fill: false,
                    borderColor: 'rgb(75, 192, 192)',
                    tension: 0.1
                }]
            },
        });
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Merk op dat bovenstaande code geen error geeft, ook al is document.getElementById('myChart') undefined voordat de data opgehaald is. Dit komt omdat de lifecycle methode componentDidUpdate pas uitgevoerd wordt nadat de render functie een tweede keer uitgevoerd is.

Refs

Bovenstaande code maakt gebruik van de core JavaScript methode document.getElementById, alhoewel dit werkt, is dit niet ideaal. React bevat een ingebouwde manier om referenties naar DOM elementen te verkrijgen.

De eerste stap is het aanmaken van de referentie in de constructor van de class component.

/src/containers/weatherListContainer.js
constructor(props) {
    super(props);

    this.state = {
        weather: undefined,
        city: 'Geel',
        latitude: 51.1659867,
        longitude: 4.9160109,
    };
    this.canvasRef = React.createRef();
}









 

1
2
3
4
5
6
7
8
9
10
11

Vervolgens moeten we aan React laten weten naar welk DOM element de referentie moet verwijzen. Dit kan door middel van de property ref die op elke component beschikbaar is. Let op, een ref kan niet toegevoegd worden aan een functiecomponent omdat deze geen instanties hebben, en de achterliggende code van refs dat nodig heeft.

/src/containers/weatherListContainer.webm
 render() {
        if (this.state.weather === undefined) {
            return <></>;
        }

        return (
            <div>
                <WeatherList daily={this.state.weather.daily} current={this.state.weather.current}
                             city={this.props.city}/>
                <div className={'m-2'}>
                    <canvas width="400" height="200" 
                            ref={this.canvasRef}/>
                </div>
            </div>
        );
    }











 




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

Tenslotte kan de referentie gebruikt worden via this.canvasRef.current.

/src/containers/weatherListContainer.js
componentDidUpdate(prevProps, prevState) {
    const ctx = this.canvasRef.current.getContext('2d');
    Chart.register(LineController, CategoryScale, LinearScale, LineElement, PointElement);
    new Chart(ctx, {
        type: 'line',
        data: {
            labels: this.state.weather.daily.map(d => new Date(d.dt * 1000).toLocaleDateString()),
            datasets: [{
                    data: this.state.weather.daily.map(d => d.temp.day),
                    borderWidth: 1,
                    fill: false,
                    borderColor: 'rgb(75, 192, 192)',
                    tension: 0.1
                }]
        },
    });
}

 















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

Hint

Maak zo weinig mogelijk gebruik van refs, de meeste dingen kunnen declaratief gedaan worden via properties. Enkel voor zaken als focus, scrollen naar een bepaald element en integratie met third party libraries zijn refs nuttig. Als je iets kan oplossen zonder een ref, dan gebruik je geen ref.

Samenvatting lifecycle

Onderstaand diagram vat de lifecycle van een React component samen.

https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/open in new window

Volledig uitgewerkte lesvoorbeelden met commentaar (zonder .env file)

Last Updated:
Contributors: Sebastiaan Henau