我有一个React组件,它应该加载6个图像的时间作为页面滚动较低。我想要YouTube和Reddit现在使用的典型的无限滚动效果。
现在,页面会像应该的那样打开,加载了6张图片。当我向下滚动时,应用程序又加载了6个,但随后就停止了。总共有25张图片。我数了数,有13张图片因为某种原因没有加载。该应用程序应该在向下滚动时一次加载6张图像,直到没有更多的图像可加载。
我使用的是无限滚动组件here。我试着安装了一个老版本'4.5.2‘,但也不起作用。
底部的应用程序屏幕截图显示了顶部的按钮,可以添加或删除6个图像。
第一个数字显示6个图像的增量。(渲染6个图像时为0,渲染12个图像时为1。)
下面的数字显示了图片总数(应用程序从后端收到的JSON对象中的图片URL)。
import React, { ListView } from 'react';
import InfiniteScroll from 'react-infinite-scroll-component';
export default class Fb_grid extends React.Component {
constructor(props) {
super(props)
this.state = {
apiResponse: [],
page: 0
}
}
componentDidMount() {
this.callAPI();
}
callAPI() {
fetch('/api/getList')
.then(res => res.json())
.then(res => this.setState({ apiResponse: res }))
}
next = () => {
this.setState({ page: this.state.page+1 })
}
render() {
const { apiResponse } = this.state;
const { page } = this.state;
if(!apiResponse) {
return <p className="row">Loading</p>
}
return(
<div className="App">
<div className="row">
<button className="testButton" onClick={this.previous}>LESS</button>
<button className="testButton" onClick={this.next}>MORE</button>
<br/>{page}<br/>{apiResponse.length}<div className="spacer"/>
</div>
<div className="row">
<InfiniteScroll
dataLength={apiResponse.length}
next={this.next}
hasMore={true}
>
{Object.values(apiResponse.slice(0, (this.state.page+1)*6)).map((value, index) =>
<a target="_blank" rel="noopener noreferrer" href={value.post}>
<img src={value.image} className="image"/>
</a>)}
</InfiniteScroll>
</div>
</div>
)
}
}

如果你想在你的机器上运行这个组件,你可能希望你自己的JSON存储在本地的组件中。当然,您还必须相应地调整Object.values(apiResponse.slice(0, (this.state.page+1)*6)).map行。
下面是我的组件使用的JSON数据。25个对象,其中包含图像URL和用于呈现图像的<a>标记的链接。
[{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"},
{"image":"https://cdn.mos.cms.futurecdn.net/vChK6pTy3vN3KbYZ7UU7k3.jpg","post":"http://www.google.com"}]发布于 2020-02-12 13:29:52
您可以使用以下延迟加载组件
import React, { Component } from 'react'
import PropTypes from 'prop-types'
const LoaderComponent = () => (
<div className='loader' >
<div className='loader-text'>Loading...</div>
</div>
)
class LazyLoadOnBody extends Component {
constructor (props) {
super(props)
this.state = {
loadMore: true,
footer: this.props.footerHeight
}
this.onScroll = this.onScroll.bind(this)
}
componentDidMount () {
window.addEventListener('scroll', this.onScroll, false)
}
componentWillReceiveProps (nextProps) {
if (nextProps.currentTotal !== this.props.currentTotal) {
this.setState({
loadMore: true
})
}
}
componentWillUnmount () {
window.removeEventListener('scroll', this.onScroll)
}
onScroll () {
const windowHeight = 'innerHeight' in window ? window.innerHeight : document.documentElement.offsetHeight
const { scrollHeight, offsetHeight } = document.body
const { clientHeight } = document.documentElement
const scrollHeightHtml = document.documentElement.scrollHeight
const offsetHeightHtml = document.documentElement.offsetHeight
const bodyHeight = Math.max(scrollHeight, offsetHeight)
const docHeight = Math.max(bodyHeight, clientHeight, scrollHeightHtml, offsetHeightHtml)
const windowBottom = windowHeight + window.pageYOffset
const { total, currentTotal } = this.props
if (windowBottom >= docHeight - 150 - this.state.footer && total > currentTotal) {
if (this.state.loadMore) {
this.props.loadMoreRows()
}
this.setState({
loadMore: false
})
}
}
render () {
return (
<div className={this.props.className} >
{this.props.children}
{!this.state.loadMore ? this.props.loader : null}
</div>
)
}
}
LazyLoadOnBody.propTypes = {
total: PropTypes.number,
currentTotal: PropTypes.number,
loadMoreRows: PropTypes.func.isRequired,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
footerHeight: PropTypes.number,
loader: PropTypes.node,
className: PropTypes.string,
}
LazyLoadOnBody.defaultProps = {
children: null,
footerHeight: 0,
loader: <LoaderComponent />,
className: '',
total: 0,
currentTotal: 0
}
export default LazyLoadOnBody您可以相应地更新您的代码
import React from 'react';
import LazyLoadBody from '../LazyLoadBody';
const Loader = () => (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: 50
}}
>
Loading...
</div>
)
export default class FbGrid extends React.Component {
constructor(props) {
super(props)
this.state = {
apiResponse: [],
page: 0
}
}
componentDidMount() {
this.callAPI();
}
callAPI() {
fetch('/api/getList')
.then(res => res.json())
.then(res => this.setState({ apiResponse: res }))
}
loadMoreRows = () => {
this.setState({ page: this.state.page + 1 })
}
render() {
const { apiResponse, page } = this.state;
if (!apiResponse) {
return <p className="row">Loading...</p>
}
return (
<div className="App">
<div className="row">
<br />{page}<br />{apiResponse.length}<div className="spacer" />
</div>
<LazyLoadOnBody loader={<Loader />} total={this.state.apiResponse.length} currentTotal={(page + 1) * 6} loadMoreRows={() => this.loadMoreRows()} >
<div className='row' >
{Object.values(apiResponse.slice(0, (page + 1) * 6)).map((value, i) => (
<a key={i} target="_blank" rel="noopener noreferrer" href={value.post}>
<img alt='' src={value.image} className="image" />
</a>
))}
</div>
</LazyLoadOnBody>
</div>
)
}
}https://stackoverflow.com/questions/60171196
复制相似问题