我目前正在自学代码,目前正在学习React.js。我正在构建一个简单的应用程序,该应用程序显示通过punkAPI(https://punkapi.com/documentation/v2)提取的啤酒信息。
在我的应用中,我想添加某种“无限”滚动,当用户到达页面底部时,该滚动将从API中提取更多数据。
目前,handleScroll方法可以工作,并更新组件的状态,但它不会触发render方法,我想知道为什么。
我意识到我的代码有很多问题,我打算对其进行重组,在this.state中添加一些布尔值以检查是否还有更多数据要加载,处理错误以及不触发handleScroll如此密集的方法。
但是,我仍然想知道为什么即使状态已更新,也没有渲染发生。
class BeerList extends Component {
constructor() {
super()
this.state = {
loading: false,
beers: []
}
this.handleScroll = this.handleScroll.bind(this)
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll, true);
this.setState({
loading: true
})
fetch("https://api.punkapi.com/v2/beers?per_page=12")
.then(response => response.json())
.then(data => {
this.setState({
loading: false,
beers: data
})
})
}
handleScroll() {
const checkForNewBeers = () => {
let lastBeerCard = document.querySelector(".beer-list > div:last-child");
let lastBeerCardOffset = lastBeerCard.offsetTop + lastBeerCard.clientHeight;
let pageOffset = window.pageYOffset + window.innerHeight;
if (pageOffset <= lastBeerCardOffset - 10) {
return;
}
this.setState(prevState => {
const beers = prevState.beers;
const page = (prevState.beers.length / 12) + 1;
fetch(`https://api.punkapi.com/v2/beers?per_page=12&page=${page}`)
.then(response => response.json())
.then(data => {
for (let item of data) {
beers.push(item);
}
console.log({
beers: beers
});
return {
beers: beers
}
});
});
}
document.addEventListener("scroll", function (event) {
checkForNewBeers();
});
}
render() {
let beerCards = []
if (this.state.beers.length > 0) {
beerCards = this.state.beers.map(beer => {
return <BeerCard
key = {
beer.id
}
img = {
beer.image_url
}
title = {
beer.name
}
description = {
beer.description
}
/>
})
}
return ( <
div className = "container" >
<
div className = "row beer-list" > {
beerCards
} <
/div> < /
div >
)
}
}
export default BeerList
因此,在页面加载时会正确附加BeerCards,然后在滚动控制台时会显示状态已更新(太多但仍然)。我希望该页面加载大量的BeerCard,但没有任何反应。为什么会这样?
答案 0 :(得分:1)
一旦调用setState中的最后一条语句fetch,就会返回未定义的内容。尝试将setState参数转换为异步函数:
this.setState(async prevState => {
const beers = prevState.beers;
const page = prevState.beers.length / 12 + 1;
let response = await fetch(
`https://api.punkapi.com/v2/beers?per_page=12&page=${page}`
);
response = await response.json();
for (const item of response) {
beers.push(item);
}
console.log({
beers: beers
});
return {
beers: beers
};
});
答案 1 :(得分:1)
不是从异步fetch
返回对象,而是在setState
内调用.then()
let beers = this.state.beers;
const page = (this.state.beers.length / 12) + 1;
fetch(`https://api.punkapi.com/v2/beers?per_page=12&page=${page}`)
.then(response => response.json())
.then(data => {
for (let item of data) {
beers.push(item);
}
this.setState({ beers });
});
答案 2 :(得分:0)
您是如此亲密!只需在“ this.setState”中的“ prevState”之前添加关键字“ async”,并在“ fetch”之前添加“ return await”,即可更新应用程序的状态并按预期触发重新渲染。