反应延迟加载/无限滚动解决方案

时间:2017-03-16 21:25:24

标签: javascript reactjs universal

我花了一些时间来弄清楚如何使用优秀的React Lazyload component延迟加载图片。

滚动时的示例延迟加载图像但是在测试时我无法获得相同的行为。

罪魁祸首是overflow: auto;,与按预期工作的组件发生冲突。

  

在React中延迟加载大型图片库/幻灯片的最佳方法是什么?

React Lazyload(真的很喜欢这个组件,但想调查其他人)

React Virtualized(看似沉重但功能丰富)

React Infinite(由于复杂性,进入门槛较高)

React Lazylist(直接向前但不确定图像是否最佳)

其他...吗

我有一个通用/同构应用程序,因此上面的某些内容会因窗口对象无法在服务器上使用而中断。

3 个答案:

答案 0 :(得分:1)

我是React Lazy Load Image Component的作者,它应该适用于同构应用程序。

答案 1 :(得分:1)

如果您想要一个更简单的延迟加载解决方案,而不必使用其他人的软件包/代码,请尝试使用IntersectionObserver API。

https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

我写了一篇有关如何使用它在React组件中延迟加载图像的中型文章(实现与香草JS基本相同)。

https://medium.com/@parkjoon94/lazy-loading-images-intersectionobserver-8c5bff730920

您只真正需要这部分代码(以上文章的摘录):

this.observer = new IntersectionObserver(
  entries => {
    entries.forEach(entry => {
      const { isIntersecting } = entry;
      if (isIntersecting) {
        this.element.src = this.props.src;
        this.observer = this.observer.disconnect();
      }
    });
  }, {}
);

答案 2 :(得分:1)

import React from "react";
import PropTypes from "prop-types";
import axios from "axios";
import InfiniteScroll from "react-infinite-scroller";
const styles = theme => ({
  root: {
    textAlign: "center",
    paddingTop: theme.spacing.unit * 20
  }
});

class Parent extends React.Component {
  state = {
    allposts: [],
    posts: [],
    hasMore: true,
    curpage: 0,
    pagesize: 30,
    totalPage: 0,
    total: 0
  };

  componentDidMount() {
    axios.get("https://jsonplaceholder.typicode.com/posts").then(res => {
      let curpage = this.state.curpage;
      let posts = res.data.slice(
        curpage * this.state.pagesize,
        (curpage + 1) * this.state.pagesize
      );
      this.setState({
        allposts: res.data,
        posts: posts,
        total: res.data.length,
        totalPage: Math.ceil(res.data.length / this.state.pagesize)
      });
    });
  }

  loadmoreItem() {
    if (this.state.curpage + 1 < this.state.totalPage) {
      let curpage =
        this.state.curpage < this.state.totalPage
          ? this.state.curpage + 1
          : this.state.curpage;
      let posts = this.state.allposts.slice(
        0,
        (curpage + 1) * this.state.pagesize
      );
      this.setState({ posts: posts, curpage });
    } else {
      this.setState({ hasMore: false });
    }
  }

  render() {
    if (this.state.posts.length === 0) return <h1>loading...</h1>;
    else {
      console.log(this.state);
      return (
        <div>
          <Table
            hasMore={this.state.hasMore}
            posts={this.state.posts}
            loadmoreItem={this.loadmoreItem.bind(this)}
          />
        </div>
      );
    }
  }
}

export default Parent;

const Table = props => {
  console.log("props: ", props);
  return (
    <React.Fragment>
      <div style={{ height: "400px", overflow: "auto" }}>
        <InfiniteScroll
          pageStart={0}
          loadMore={props.loadmoreItem}
          hasMore={props.hasMore}
          loader={
            <div className="loader" key={0}>
              Loading ...
            </div>
          }
          useWindow={false}
          threshold={350}
        >
          <table>
            <tr>
              <th>id</th>
              <th>title</th>
              <th>body</th>
            </tr>
            {props.posts.map(item => {
              return (
                <tr>
                  <td>{item.id}</td>
                  <td>{item.title}</td>
                  <td>{item.body}</td>
                </tr>
              );
            })}
          </table>
        </InfiniteScroll>
      </div>
      <button onClick={props.loadmoreItem}>next</button>
    </React.Fragment>
  );
};
  

这里查看即时示例

https://codesandbox.io/s/x228lmm90q