Javascript 在启动时从api获取所有数据
首先,我想让您知道我只是从React和contextapi开始 以下是我的情况:我想在应用程序启动时从中取出所有啤酒(在取出时显示加载器),并将所有这些啤酒放在上下文中以访问子组件 我的问题是API没有给出所有beers页面的总数,所以我必须检查结果的长度,当长度等于0时停止抓取,然后将数据置于状态 然后,一旦加载了所有内容,我想向所有啤酒添加一个属性(favorite),并首先将其设置为false,然后,如果用户登录,检索他的收藏夹,并在与收藏夹列表相关的上下文中将其设置为true 以下是我目前的情况:Javascript 在启动时从api获取所有数据,javascript,reactjs,recursion,fetch-api,Javascript,Reactjs,Recursion,Fetch Api,首先,我想让您知道我只是从React和contextapi开始 以下是我的情况:我想在应用程序启动时从中取出所有啤酒(在取出时显示加载器),并将所有这些啤酒放在上下文中以访问子组件 我的问题是API没有给出所有beers页面的总数,所以我必须检查结果的长度,当长度等于0时停止抓取,然后将数据置于状态 然后,一旦加载了所有内容,我想向所有啤酒添加一个属性(favorite),并首先将其设置为false,然后,如果用户登录,检索他的收藏夹,并在与收藏夹列表相关的上下文中将其设置为true 以下是我目
在这个错误中,它表示您试图在defaultBeersContext中循环通过空beers=null数组 我认为您的意图是从API加载啤酒数据以填充啤酒的状态,然后通过填充的啤酒数组forEach 出现错误是因为以下行是异步的,并且在您尝试访问其返回的数据之前未完成:
this.fetchAllBeers(1, []).then(result => this.setState({beers: result}))
因此在下一行
this.state.beers.forEach(...)
该状态仍然包含旧的默认啤酒默认数据(啤酒:null),因为您的前一行尚未完成啤酒数据的获取
如果您使用的是Promissions,那么在运行forEach之前,您需要等待获取新的beers数据,如下所示:
this.fetchAllBeers(1, [])
.then(result => {
this.setState({beers: result});
allBeers.forEach(beer => (beer.favorite = false));
...
})
您之所以想这样做,是因为您的以下行取决于获取啤酒数据的完成。谢谢您@Shawn Andrews的帮助,我现在更了解承诺背后的过程。我最终决定将我的收藏夹和啤酒合并到一个儿童容器组件中,让beersContext获取所有内容,userContext获取收藏夹。然后,容器组件将两者合并,然后将修改后的值传递给渲染组件 这是我最后的啤酒背景:
import React from 'react'
import {jsonFetch} from 'easyfetch'
import _ from 'lodash'
import {UserAuthContext} from './UserContext'
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
}
componentDidMount() {
this.fetchAllBeers(1, [])
}
async fetchAllBeers(page, beers) {
await jsonFetch(`https://api.punkapi.com/v2/beers?page=${page}&per_page=80`)
.get()
.then(data => {
if (data && data.length > 0) {
data.forEach(item => (item.favorite = false))
this.fetchAllBeers(page + 1, _.concat(beers, data))
} else {
this.setState({beers, isFetchingBeers: false})
}
})
.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, fetchAllBeers: this.fetchAllBeers}}>
{children}
</BeersContext.Provider>
)
}
}
BeersProvider.contextType = UserAuthContext
从“React”导入React
从“easyfetch”导入{jsonFetch}
从“lodash”导入
从“./UserContext”导入{UserAuthContext}
常量defaultBeersContext={
啤酒:零,
是的,
errorFetchingBeers:null,
}
export const BeersContext=React.createContext(defaultBeersContext)
导出默认类BeersProvider扩展React.Component{
建造师(道具){
超级(道具)
this.state=defaultBeersContext
}
componentDidMount(){
这个。获取所有啤酒(1,[])
}
异步获取所有啤酒(第页,啤酒){
等待jsonFetch(`https://api.punkapi.com/v2/beers?page=${page}&per_page=80`)
.get()
。然后(数据=>{
如果(数据和数据长度>0){
data.forEach(item=>(item.favorite=false))
this.fetchAllBeers(第+1页,u.concat(啤酒,数据))
}否则{
this.setState({beers,isFetchingBeers:false})
}
})
.catch(error=>this.setState({errorFetchingBeers:error,isFetchingBeers:false}))
}
render(){
const{children}=this.props
const{beers,isFetchingBeers,errorFetchingBeers}=this.state
返回(
{儿童}
)
}
}
BeersProvider.contextType=UserAuthContext
this.fetchAllBeers(1, [])
.then(result => {
this.setState({beers: result});
allBeers.forEach(beer => (beer.favorite = false));
...
})
import React from 'react'
import {jsonFetch} from 'easyfetch'
import _ from 'lodash'
import {UserAuthContext} from './UserContext'
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
}
componentDidMount() {
this.fetchAllBeers(1, [])
}
async fetchAllBeers(page, beers) {
await jsonFetch(`https://api.punkapi.com/v2/beers?page=${page}&per_page=80`)
.get()
.then(data => {
if (data && data.length > 0) {
data.forEach(item => (item.favorite = false))
this.fetchAllBeers(page + 1, _.concat(beers, data))
} else {
this.setState({beers, isFetchingBeers: false})
}
})
.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, fetchAllBeers: this.fetchAllBeers}}>
{children}
</BeersContext.Provider>
)
}
}
BeersProvider.contextType = UserAuthContext