Tot nu toe hebben we de data rechtstreeks van de applicatie code zelf gebruikt. In de meeste dynamische webapplicaties gebruik je een externe web service met een of andere dataopslag (SQL-database, files, ...). In dit deel gaan we onze webapplicatie aanpassen zodat die gebruik maakt van de Movie Web Service.
Bij het oproepen van een web service krijg je nooit direct het antwoord terug. Er zal altijd een kleine vertraging opzitten omdat deze via het internet zal verlopen, daarom moet deze asynchroon gebeuren. Soms wordt zo'n web service call ook een AJAX call genoemd.
Er zijn veel verschillende libraries om AXJAX calls te maken in React applicaties. Hieronder vindt je een lijst van veel gebruikte libraries:
Axios
Fetch (ingebouwd in elke browser)
Superagent
React-axios
Use-http
React-request
We kunnen hier in principe eender welke library gebruiken maar we gaan Fetch gebruiken omdat deze geen externe library nodig heeft en ingebouwd is in elke moderne browser.
Omdat onze games niet meer in het begin beschikbaar zijn in onze applicatie zorgen we er nu voor dat de state op een lege array wordt gezet bij het initializeren van het App
component.
We gaan nu even terug naar wat we gezien hebben in het onderdeel side-effects
. We hebben daar de useEffect
hook gezien en we hebben daar afgesproken dat alle dingen die bestaat uit communicatie met een externe service via effects moet gebeuren. We hebben daar ook gezien dat we altijd een lege array mee moeten geven als we deze effect maar 1 keer willen laten uitvoeren bij de eerste render van het component.
Je ziet hier dat we voorlopig toch gewoon onze initiële array hier opvullen met onze voorbeeld data. We vullen deze wel pas op na 1 seconde. Dit doen we aan de hand van de javascript setTimeout
functie. We doen dit omdat we soms een API call willen nabootsen om dingen eerst te testen of omdat de API op dat moment nog niet klaar is. De reden dat we pas de setGame
gebruiken na 1 seconde is omdat we een tragere netwerk request willen naboosten die ongeveer 1 seconde duurt.
Als je nu naar onze webapplicatie naar de /list
path zou gaan met je browser zal je zien dat de lijst eerst leeg zal zijn en dan na een seconde gevuld zal worden. Dit kan voor de gebruiker een beetje raar zijn, daarom gaan we nu een extra updating
state invoeren zodat we een loading indicator kunnen laten zien aan de gebruiker terwijl de data laadt.
Bij aanvang van onze nagemaakte API call zetten we updating
op true en nadat de data is aangepast dan zetten we deze terug op false.
We kunnen nu nakijken of updating
op true staat voordat we de rest van onze layout gaan renderen. Als updating
true is dan tonen we een div
met de text 'Loading data' en anders tonen we gewoon onze Switch
van onze routing.
We kunnen deze loading text ook nog vervangen met een loading spinner aan de hand van wat css magie:
en in onze App.module.css
maken we dan deze classes aan zodat we deze loader kunnen laten draaien aan de hand van keyframes
We gaan nu de eigenlijke web service aanspreken om de games op te halen. We maken een aparte functie voor het ophalen van games van de API. De getGames
functie duiden we aan als async
functie omdat we er gebruik gaan maken van async/await
omdat er asynchrone code in deze functie staat (het ophalen van de games via de API).
Net als bij de nagebootste call van hiervoor zetten we eerst de updating
state eerst op true. Vervolgens doen we de fetch
call naar http://localhost:3001/games
met de GET methode. Deze fetch methode geeft de response terug als stream, dus deze moet nog helemaal omgezet worden naar json aan de hand van de response.json()
methode. Beide fetch
en json
zijn functies die een promise terug geven dus hiervoor kan het await
keyword geplaatst worden zodat er gewacht wordt tot de promise afgehandeld is. Als we het resultaat volledig hebben gebruiken we de setGames
methode om de state van de games aan te passen.
Nu kunnen we deze methode aanroepen in onze effect
Met Fetch kunnen we uiteraard ook POST requests doen naast GET requests. Zo kunnen we heel eenvoudig onze handleAdd
functie aanpassen zodat die nu een Game toevoegt aan de hand van de POST op /games
. Net als bij de getGames
zetten we eerst setUpdating
op true zodat de loader getoond wordt. We geven nu een method: POST
mee aan de fetch functie en plaatsen we het game object in de body. We moeten het wel eerst naar string omzetten. De POST op /games
geeft een json terug met alle games in zodat we deze response kunnen gebruiken om onze games
state te updaten.