Les 4: Context & Fetching data
Les 4: Context & Fetching data
Tijdens deze oefeningenreeks bouw je een applicatie waarmee je de meest populaire en recente artikels op Hacker News kan bekijken. Je oefent op
- De concepten van de eerste 3 lessen
- Data ophalen via Axios
- Het gebruik van TanStack Query
- Het lezen van API documentatie
- Het gebruik van Suspense
Oefening 1: API-code
Schrijf, met behulp van Axios, twee functies. De eerste functie moet de meeste populaire stories, ask stories, show stories of job stories ophalen. De functie krijgt één argument, het endpoint dat gebruikt moet worden. Je schrijft dus één functie die alle 4 van de bovenstaande endpoints kan aanspreken. De tweede functie haalt één item op, op basis van een id, gebruik hiervoor het get by id endpoint.
Schrijf vervolgens twee custom hooks, useGetItemIds en useGetItem die respectievelijk gebruik maken van de eerste en tweede functie die je hierboven geschreven heb en gebruik maken react query.
Oefening 2: Context
Maak een nieuwe context aan. Deze context bevat een variabele darkTheme en refetchInterval alsook methodes om deze waarden aan te passen. De variabele darkTheme geeft aan of de gebruiker al dan niet gekozen heeft om het donkere thema te activeren (standaard true). De variabele refetchInterval geeft aan om de hoeveel tijd react query de data moet ververst worden. Voorzie een provider en zorg er vervolgens voor dat het refetchInterval gebruikt wordt in de useGetItemIds en useGetItem hooks.
Oefening 3: Tabs
Maak gebruik van de react bootstrap Tabs component om onderstaand menu na te bouwen. Onderstaande array bevat de data die gebruikt kan worden om de tabs op te bouwen in een lus. Om onderstaande layout te bouwen kan je de volledige app omringen in een Container component. Deze component kan je vervolgens omringen in onderstaande styled component. Daarnaast kan je ook het menu omringen in volgende component.
const endpoints = [
{
id: 0,
title: 'Top Stories',
endpoint: 'topstories.json'
},
{
id: 1,
title: 'Ask Hacker News',
endpoint: 'askstories.json'
},
{
id: 2,
title: 'Show Hacker News',
endpoint: 'showstories.json'
},
{
id: 3,
title: 'Jobs',
endpoint: 'jobstories.json'
}
]
const StyledContainerWrapper = styled.div`
background-color: ${props => props.darkTheme ? '#1d2025' : 'white'};
color: ${props => props.darkTheme ? '#688f9e': 'black'};
a {
color: ${props => props.darkTheme ? '#688f9e' : 'black'};
}
button {
color: ${props => props.darkTheme ? '#688f9e' : 'black'};
}
min-height: 100vh;
min-width: 100vw;
`
const StyledTabsWrapper = styled.div`
background-color: ${props => props.darkTheme ? '#1d2025' : 'white'};
ul > li > button, li {
background-color: ${props => props.darkTheme ? '#1d2025' : 'white'} !important;
border-bottom: 1px solid ${props => props.darkTheme ? '#228f61' : '#1d2025'} !important;
}
ul > li > button:hover, ul > li > button.active, ul > li > button:active, ul > li > button:focus {
border: 1px solid ${props => props.darkTheme ? '#228f61' : '#1d2025'} !important;
}
ul {
border-bottom: 2px solid ${props => props.darkTheme ? '#228f61' : '#1d2025'} !important;
}
`

Oefening 4: Settings pagina
Als je op het settings tab drukt, moet de Settings component zichtbaar worden. Deze component kan gebruikt worden om de waarden in de context aan te passen. Als je de dark/light toggle aanpast, moet je onmiddellijk het resultaat zien.


Oefening 5: Top stories
Schrijf een component TopItems, deze component wordt in elk van de 4 overige tabs getoond. De component krijgt één property mee, het endpoint dat gebruikt moet worden om de stories op te halen voor het geselecteerde tabblad. Deze component wordt omringt door Suspense en toont de LoadingPage component die beschikbaar is in de startbestanden.

Binnen de TopItems component worden natuurlijk de ids opgehaald van de top stories in de geselecteerde categorie. Vervolgens worden voor de eerste 10 stories in deze lijst, de details opgehaald.
De stories zien er als volgt uit, de titel is een link naar de website waarover het story gaat (als deze er is), de discuss link verwijst door naar een detailpagina voor het story. Raadpleeg de documentatie voor meer informatie over de exacte property namen. Onderstaande component is gebouwd met behulp van een Card.

Onder de stories wordt een knop getoond waarmee de volgende 10 stories ingeladen kunnen worden. De vorige stories blijven zichtbaar. Terwijl de nieuwe stories aan het laden zijn, wordt een loading animation getoond, deze is gebouwd met de react bootstrap Placeholder component. Je hebt hier dus opnieuw suspense nodig.

Onderstaande video demonstreert de volledige werking van de stories pagina.
Oefening 6: Details pagina
De detailpagina kan geopend worden als de gebruiker op de discuss knop drukt. Tijdens het laden van de applicatie wordt opnieuw de LoadingPage component getoond en wordt er opnieuw gebruik gemaakt van de useGetItem hook.

Zodra de data geladen is, wordt de titel van het story getoond, voor de titel staat een pijl waarmee terug naar de hoofdpagina genavigeerd kan worden. Daarnaast wordt ook de tekst van het story getoond (als deze er is). Deze tekst is in HTML formaat, dit betekent dat je gebruik moet maken van de dangerouslySetInnerHTML property die op elk HTMLElement beschikbaar is in HTML. Deze property werkt als volgt:
const SomeComponent = () => {
return (
<>
<div dangerouslySetInnerHTML={{__html: `<p>Some HTML code</p>`}}/>
</>
)
}

Oefening 6.1: Commentaar
Elk item dat op de detailpagina weergegeven wordt heeft een property (zie docs) die een lijst van ids van de commentaren bevat. Deze ids kunnen gebruikt worden, om via de useGetItem hook de commentaren op te halen. Deze tekst in deze commentaren is omringt in onderstaande component.
const CommentContent = styled.div`
margin-left: 1.5em;
border: .5px solid #455a64;
padding: .5em;
margin-bottom: 1em;
width: 95%;
`
De niveau 1 commentaren worden opgehaald voordat de pagina getoond wordt. De commentaren kunnen open en dichtgeklapt worden, je kan gebruik maken van de HTML-entiteiten ∧ (∧) en ∨ (∨) om aan te geven of de commentaar open of dichtgeklapt is. Om de datum van de commentaar correct weer te geven, moet de unix timestamp (in seconden) die je van de API terugkrijgt geconverteerd worden naar een JavaScript timestamp (in milliseconden). De JavaScript timestamp kan meegegeven worden als argument aan de Date klasse (new Date(timestamp)). Tenslotte kan je de toLocaleString() gebruiken om een goede representatie te krijgen (op basis van de locale instellingen in de browser).

Oefening 6.2: Geneste commentaren
Op een commentaar kunnen eventueel ook commentaren geplaatst worden. Als er geneste commentaren zijn, moet een knop Show comments... getoond worden. Zodra de gebruiker op deze knop drukt, wordt deze verborgen en worden de geneste commentaren via suspense getoond. Terwijl deze aan het laden zijn, wordt de LoadingPart component getoond, die beschikbaar is in de startbestanden. De geneste commentaren maken opnieuw gebruik van dezelfde component die je al gebruikt hebt voor de niveau 1 componenten. Deze werkwijze zet zich voort tot er geen diepere commentaren meer zijn.