Прежде всего, я хотел бы сообщить, что я только начинаю с React и Context API.
Вот моя ситуация: я хотел бы получить все пиво из PunkAPI при запуске приложения (отображение загрузчика во время выборки) и размещение всего этого пива в контексте для доступа к его подкомпонентам.
Моя проблема заключается в том, что API не даетобщее количество страниц пива, поэтому я должен проверить длину результатов и прекратить получать, когда длина равна 0, а затем поместить данные в состояние.
Затем, как только все будет загружено, я хотел быдобавить свойство ( favourite ) для всех сортов пива и сначала установить для него значение false, а затем, если пользователь вошел в систему, получить его избранное и установить для него значение true для каждого пива в контексте, который касаетсяпо списку избранных.
Вот то, с чем я пришел сейчас:
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
PS: Я использую jsonFetch отсюда: easyfetch
Но это не работает, говоря:
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')