Javascript 无限滚动组件在向下滚动时仅加载一个新的对象切片,然后停止
我有一个React组件,当页面向下滚动时,它应该一次加载6个图像。我想要YouTube和Reddit现在使用的典型无限滚动效果 现在页面打开了,加载了6幅图像。当我向下滚动时,应用程序会加载另一个6,但随后停止。总共有25张图片。我统计了13个由于某种原因没有加载的图像。该应用程序应该在向下滚动时一次加载6个图像,直到没有更多图像可加载为止 我正在使用无限滚动组件。我尝试过安装一个旧版本号“4.5.2”,但也没有成功 底部的应用程序屏幕截图显示顶部的按钮,可添加或删除6幅图像。Javascript 无限滚动组件在向下滚动时仅加载一个新的对象切片,然后停止,javascript,reactjs,npm,Javascript,Reactjs,Npm,我有一个React组件,当页面向下滚动时,它应该一次加载6个图像。我想要YouTube和Reddit现在使用的典型无限滚动效果 现在页面打开了,加载了6幅图像。当我向下滚动时,应用程序会加载另一个6,但随后停止。总共有25张图片。我统计了13个由于某种原因没有加载的图像。该应用程序应该在向下滚动时一次加载6个图像,直到没有更多图像可加载为止 我正在使用无限滚动组件。我尝试过安装一个旧版本号“4.5.2”,但也没有成功 底部的应用程序屏幕截图显示顶部的按钮,可添加或删除6幅图像。 第一个数字显示6
第一个数字显示6个图像的增量。(渲染6个图像时为0,渲染12个图像时为1。)
下面的数字显示了图像总数(应用程序从后端接收到的JSON对象中的图像URL)
您可以使用以下延迟加载组件
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,{Component}来自“React”
从“道具类型”导入道具类型
常量加载组件=()=>(
加载。。。
)
类LazyLoadOnBody扩展组件{
建造师(道具){
超级(道具)
此.state={
loadMore:是的,
页脚:this.props.footerHeight
}
this.onScroll=this.onScroll.bind(this)
}
组件安装(){
window.addEventListener('scroll',this.onScroll,false)
}
组件将接收道具(下一步){
if(nextrops.currentTotal!==this.props.currentTotal){
这是我的国家({
loadMore:是的
})
}
}
组件将卸载(){
window.removeEventListener('scroll',this.onScroll)
}
onScroll(){
const windowHeight='innerHeight'在window?window.innerHeight:document.documentElement.offsetHeight中
const{scrollHeight,offsetHeight}=document.body
const{clientHeight}=document.documentElement
常量scrollHeightHtml=document.documentElement.scrollHeight
const offsetHeight html=document.documentElement.offsetHeight
const bodyHeight=Math.max(滚动高度,离视)
const docHeight=Math.max(车身高度、clientHeight、滚动高度HTML、Offsetheight HTML)
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()
}
这是我的国家({
loadMore:错误
})
}
}
渲染(){
返回(
{this.props.children}
{!this.state.loadMore?this.props.loader:null}
)
}
}
LazyLoadOnBody.propTypes={
总计:PropTypes.number,
currentTotal:PropTypes.number,
loadMoreRows:PropTypes.func.isRequired,
儿童:PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
页脚高度:PropTypes.number,
加载程序:PropTypes.node,
类名:PropTypes.string,
}
LazyLoadOnBody.defaultProps={
children:null,
页脚高度:0,
加载器:,
类名:“”,
总数:0,
现时总数:0
}
导出默认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>
)
}
}
从“React”导入React;
从“../LazyLoadBody”导入LazyLoadBody;
常量加载器=()=>(
加载。。。
)
导出默认类FbGrid扩展React.Component{
建造师(道具){
超级(道具)
此.state={
答复:[],
页码:0
}
}
componentDidMount(){
这是callAPI();
}
callAPI(){
获取('/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;
如果(!apiResponse){
return正在加载
}
返回(
{page}
{apiResponse.length}
this.loadMoreRows()}>
{Object.values(apiResponse.slice(0,(第+1页)*6)).map((值,i)=>(
))}
)
}
}
谢谢您的回答。不过,我今天实现了这个,它给了我同样的问题。当页面呈现时,它加载6,我向下滚动,它加载另一个6,但随后它停止。在本例中,它表示“正在加载”。我不明白为什么其他13张照片都不会。他们在那里。在我的示例代码中,它使用我输入的测试按钮加载所有25个。我想知道Object.values(apiResponse)
JSON是否需要以其他方式存储。虽然,就像我说的,测试按钮在它上面工作得很好。
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>
)
}
}