状态改变了,但是 react 的 render 方法没有触发
The state changed but the render method from react does not trigger
我目前正在自学代码并正在潜入 React.js。我正在构建一个简单的应用程序,它显示通过朋克 API (https://punkapi.com/documentation/v2).
提取的啤酒信息
在我的应用程序中,我想添加某种 "infinite" 滚动,当用户到达页面底部时,它会从 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 会正确附加,然后当您滚动控制台时,会显示状态已更新(太多但仍然如此)。我希望该页面加载大量 BeerCards,但什么也没有发生。这是为什么?
一旦调用setState 中的最后一条语句fetch,就会返回undefined。尝试将 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
};
});
不是从异步 fetch
返回对象,而是在 .then()
中调用 setState
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 });
});
你太亲密了!通过简单地在 "this.setState" 中的 "prevState" 前面添加关键字 "async" 和 "fetch" 前面的 "return await" ,您的应用程序的状态应该被更新并触发按预期重新渲染。
我目前正在自学代码并正在潜入 React.js。我正在构建一个简单的应用程序,它显示通过朋克 API (https://punkapi.com/documentation/v2).
提取的啤酒信息在我的应用程序中,我想添加某种 "infinite" 滚动,当用户到达页面底部时,它会从 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 会正确附加,然后当您滚动控制台时,会显示状态已更新(太多但仍然如此)。我希望该页面加载大量 BeerCards,但什么也没有发生。这是为什么?
一旦调用setState 中的最后一条语句fetch,就会返回undefined。尝试将 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
};
});
不是从异步 fetch
返回对象,而是在 .then()
setState
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 });
});
你太亲密了!通过简单地在 "this.setState" 中的 "prevState" 前面添加关键字 "async" 和 "fetch" 前面的 "return await" ,您的应用程序的状态应该被更新并触发按预期重新渲染。