2018年12月4日火曜日

無限スクロールというか無限ページングを実施するためのjavascriptというかreactの書き方的なお話

  • このエントリーをはてなブックマークに追加

jQueryを使うような記事が多いので、使わないような書き方をば。
ちなみに前提としてReact環境下だけど。

export default class HomeScreen extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      data: [],
      fetching: false,
      cursor: null,
      complete: false,
    };

    this.ItemsRef = React.createRef();
  }

  async componentDidMount() {
    const res = await this.getData();
    this.setState({ data: res.data, cursor: res.pager.next_cursor_id });

    window.addEventListener('scroll', this.onWindowScroll, false);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.onWindowScroll, false);
  }

  onWindowScroll = () => {
    const { top, height } = this.ItemsRef.current.getBoundingClientRect();

    if (top + height <= window.innerHeight) {
      this.onScrollEnd();
    }
  }

  onScrollEnd = async () => {
    const {
      data,
      cursor,
      fetching,
      complete,
    } = this.state;

    if (!fetching && !complete) {
      const res = await this.getData(cursor);
      this.setState({ data: data.concat(res.data), cursor: res.pager.next_cursor_id });
    }
  }

  getData = async (cursor = null) => {
    const { keyword } = this.state;

    this.setState({ fetching: true });

    const res = await api.data.search({
      cursor: {
        next_id: cursor,
      },
    });

    this.setState({ fetching: false, complete: !res.pager.next_cursor_id });

    return res;
  }

  ...
}

とりあえずscrollイベントを定義してあげて、その中で該当するコンポーネントの末尾が画面下部に表示されたらっていう感じ。
getBoundingClientRect()を使って要素のtopとheightを取得して、それらを足したものがwindow.innerHeightよりも小さくなればよい。
けどこれは相対的な考えだからちょっとわかりづらい場合は両方にwindow.pageYOffsetを足してあげると絶対的な考えになるからわかりやすいかも。

ってな感じでやってあげれば簡単にできるのでおすすめ的なみたいな。

Adsense