First of, I'd like to let you know I'm just starting with React and the Context API.
Here is my situation : I'd like to fetch all beers from the PunkAPI at the startup of the app (displaying a loader while fetching) and put all those beers in a context to access it to sub-components.
My issue is that the API doesn't give the total of all beers pages so I have to check the length of the results and stop fetching when the length is equal to 0 then put the data in the state.
Then, once everything is loaded, I'd like to add a property (favorite) to all the beers and set it to false first, then, if the user is logged in, retrieve his favorites and set it to true for each beer in the context that is concerned by the list of favorites.
Here is what I came with for now :
import React from 'react'
import {jsonFetch} from 'easyfetch'
import _ from 'lodash'
import {UserAuthContext} from './userContext'
import {db} from '../firebase'
const defaultBeersContext = {
beers: null,
isFetchingBeers: true,
errorFetchingBeers: null,
}
export const BeersContext = React.createContext(defaultBeersContext)
export default class BeersProvider extends React.Component {
constructor(props) {
super(props)
this.state = defaultBeersContext
}
async componentDidMount() {
let allBeers = await this.fetchAllBeers(1, [])
allBeers.forEach(beer => (beer.favorite = false))
console.log(allBeers.length)
console.log(allBeers)
const {isUserSignedIn, user} = this.context
if (isUserSignedIn && user) {
db.collection('users')
.doc(user.uid)
.get()
.then(doc => {
const favoriteBeers = doc.data().favorites
favoriteBeers.forEach(elem => {
const index = allBeers.findIndex(beer => beer.id === elem)
allBeers[index].favorite = true
})
})
}
this.setState({beers: allBeers, isFetchingBeers: false})
}
fetchAllBeers(page, beers) {
jsonFetch(`https://api.punkapi.com/v2/beers?page=${page}&per_page=80`)
.get()
.then(data => {
if (data && data.length > 0) {
this.fetchAllBeers(page + 1, _.concat(beers, data))
} else {
return beers
}
})
.catch(error => this.setState({errorFetchingBeers: error, isFetchingBeers: false}))
}
render() {
const {children} = this.props
const {beers, isFetchingBeers, errorFetchingBeers} = this.state
return (
<BeersContext.Provider value={{beers, isFetchingBeers, errorFetchingBeers}}>{children}</BeersContext.Provider>
)
}
}
BeersProvider.contextType = UserAuthContext
P.S : The jsonFetch I'm using comes from here : easyfetch
But that is not working, saying :
Unhandled Rejection (TypeError): Cannot read property 'forEach' of null
21 | async componentDidMount() {
22 | this.fetchAllBeers(1, []).then(result => this.setState({beers: result}))
> 23 | this.state.beers.forEach(beer => (beer.favorite = false))
| ^ 24 | const {isUserSignedIn, user} = this.context
25 | if (isUserSignedIn && user) {
26 | db.collection('users')