首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无限滚动React组件在向下滚动时仅加载一个新的对象切片,然后停止

无限滚动React组件在向下滚动时仅加载一个新的对象切片,然后停止
EN

Stack Overflow用户
提问于 2020-02-11 22:31:16
回答 1查看 132关注 0票数 0

我有一个React组件,它应该加载6个图像的时间作为页面滚动较低。我想要YouTube和Reddit现在使用的典型的无限滚动效果。

现在,页面会像应该的那样打开,加载了6张图片。当我向下滚动时,应用程序又加载了6个,但随后就停止了。总共有25张图片。我数了数,有13张图片因为某种原因没有加载。该应用程序应该在向下滚动时一次加载6张图像,直到没有更多的图像可加载。

我使用的是无限滚动组件here。我试着安装了一个老版本'4.5.2‘,但也不起作用。

底部的应用程序屏幕截图显示了顶部的按钮,可以添加或删除6个图像。

第一个数字显示6个图像的增量。(渲染6个图像时为0,渲染12个图像时为1。)

下面的数字显示了图片总数(应用程序从后端收到的JSON对象中的图片URL)。

代码语言:javascript
复制
    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>标记的链接。

代码语言:javascript
复制
[{"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"}]
EN

回答 1

Stack Overflow用户

发布于 2020-02-12 13:29:52

您可以使用以下延迟加载组件

代码语言:javascript
复制
    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

您可以相应地更新您的代码

代码语言:javascript
复制
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>
    )
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60171196

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档