Определите нижнюю часть страницы, чтобы получить больше данных в ответ - PullRequest
0 голосов
/ 04 февраля 2019

Я попробовал несколько кодов из нескольких ресурсов, чтобы определить, достиг ли пользователь уже нижней части страницы, а затем получить больше данных.Это работает, но функция всегда извлекает данные всякий раз, когда я прокручиваю, а не когда пользователь достигает дна.Вот мой код:

import React, { Component } from 'react';

class DataView extends Component {
  constructor(props) {
    super(props);

    this.state = {
      displayedData: [],
      initialData: [],
      loadingState: false,
    };

    this.fetchMoreData = this.fetchMoreData.bind(this);
    this.handleScroll = this.handleScroll.bind(this);
  }

  componentDidMount() {
    window.addEventListener('scroll', this.handleScroll, true);
  }

  componentWillReceiveProps(props) {
    const initialData = props.initialData;

    this.setState({
      initialData,
      displayedData: initialData.slice(0, 3),
    });
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll, true);
  }

  fetchMoreData() {
    console.log('fetch');
    this.setState({ loadingState: true });

    if (this.state.displayedData.length >= this.state.initialData.length) {
      this.setState({
        loadingState: false,
      });
      return;
    }

    const size = 3;
    const initialData = this.state.initialData;
    const copiedinitialData = [...initialData];
    const prevDisplayedData = this.state.displayedData;
    const copiedPrevDisplayedData = [...prevDisplayedData];
    const copiedPrevDisplayedDataLength = copiedPrevDisplayedData.length;
    const nextItem = copiedinitialData.slice(copiedPrevDisplayedDataLength, copiedPrevDisplayedDataLength + size);
    copiedPrevDisplayedData.push(...nextItem);

    setTimeout(() => {
      this.setState({
        displayedData: copiedPrevDisplayedData,
      });
    }, 2000);
    // use set timeout because fetching data still use mock data (not hitting API)
  }

  handleScroll() {
    // FIRST TRIAL
    // const scrollTop = document.getElementById('isScrolling').scrollTop;
    // const clientHeight = document.getElementById('isScrolling').clientHeight;
    // const scrollHeight = document.getElementById('react-element').scrollHeight; // the id is written in another component as the outer element/wrapper

    // console.log('============= ### =============');
    // console.log('scrollTop: ', scrollTop);
    // console.log('clientHeight: ', clientHeight);
    // console.log('scrollHeight: ', scrollHeight);
    // console.log('scrollHeight2: ', scrollHeight2);
    // console.log('============= ### =============');
    // if (scrollTop + clientHeight >= scrollHeight) {
    //  this.fetchMoreData();
    // }
    // above working but always fetch when scrolled, not when user reach bottom

    // SECOND TRIAL
    // const lastDiv = document.querySelector('#isScrolling > div:last-child');
    // const lastDivOffset = lastDiv.offsetTop + lastDiv.clientHeight;
    // const pageOffset = window.pageYOffset + window.innerHeight;
    // console.log('============= ### =============');
    // console.log('lastDivOffset: ', lastDivOffset);
    // console.log('pageOffset: ', pageOffset);
    // console.log('clientHeight: ', document.getElementById('isScrolling').clientHeight);
    // console.log('scrollHeight: ', document.getElementById('isScrolling').scrollHeight);
    // console.log('lastDivOffsetTop: ', lastDiv.offsetTop);
    // console.log((pageOffset / lastDivOffset) * 100);
    // console.log('============= ### =============');

    // const ratio = (pageOffset / lastDivOffset) * 100;
    // let scenario = ratio < 60;
    // let scenario = pageOffset > lastDivOffset - 10;
    // if (scenario) {
    //   this.fetchMoreData();
    // }
    // both of the scenario behave like the first trial

    console.log('============= ### =============');
    console.log('win screen: ', window.screen);
    console.log('win screenTop: ', window.screenTop);
    console.log('win screenLeft: ', window.screenLeft);
    console.log('win screenY: ', window.screenY);
    console.log('win scrollY: ', window.scrollY);
    console.log('win innerHeight: ', window.innerHeight); // always 580
    console.log('win pageYOffset: ', window.pageYOffset);
    console.log('docEl clientHeight: ', document.documentElement.clientHeight);
    console.log('docEl clientLeft: ', document.documentElement.clientLeft);
    console.log('docEl clientTop: ', document.documentElement.clientTop);
    console.log('docEl offsetHeight: ', document.documentElement.offsetHeight);
    console.log('docEl scrollHeight: ', document.documentElement.scrollHeight);
    console.log('docEl scrollLeft: ', document.documentElement.scrollLeft);
    console.log('docEl screenTop: ', document.documentElement.scrollTop);
    console.log('docBody clientHeight: ', document.body.clientHeight);
    console.log('docBody clientLeft: ', document.body.clientLeft);
    console.log('docBody clientTop: ', document.body.clientTop);
    console.log('docBody offsetHeight: ', document.body.offsetHeight);
    console.log('docBody scrollHeight: ', document.body.scrollHeight);
    console.log('docBody scrollLeft: ', document.body.scrollLeft);
    console.log('docBody screenTop: ', document.body.scrollTop);
    console.log('docId scrollHeight: ', document.getElementById('isScrolling').scrollHeight); // ==> A
    console.log('docId screenLeft: ', document.getElementById('isScrolling').scrollLeft);
    console.log('docId scrollTop: ', document.getElementById('isScrolling').scrollTop);
    console.log('docId clientHeight: ', document.getElementById('isScrolling').clientHeight); // ==> B
    console.log('docId offsetHeight: ', document.getElementById('isScrolling').offsetHeight); // ==> C
    // the A value is always 20px greater than B and C. B and C is always same value. The others console.log result is zero
    console.log('============= ### =============');

    if ((window.scrollY + window.innerHeight) >= document.body.scrollHeight) {
      // this if statement also behave like the first trial
      this.fetchMoreData();
    }
  }

  render() {
    const displayedData = this.state.displayedData.map((item, index) => {
      const itemIndex = index;
      const dataName = item.dataName;

      return <div key={itemIndex} style={{ marginBottom: 20 }}>
        {dataName}
             </div>;
    });

    return (
      <div>
        <div className="class">
          <div className="name">
            {/* {another code} */}
          </div>
          <div className="classes">
            {/* {another code} */}
          </div>
          <div id="isScrolling">
            {displayedData}
            {this.state.loadingState
              ? <div> Loading ....</div>
              : <div> No more data available</div>
            }
          </div>
        </div>
      </div>
    );
  }
}
export default DataView;

Моя цель: когда пользователь с определенного пикселя снизу, this.fetchMoreData будет запущен.Любая помощь будет очень полезна.

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Поместите это в свой componentWillMount ()

window.addEventListener('scroll', function() {
   if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
      console.log("you're at the bottom of the page");
      //show loading spinner and make fetch request to api
   }
});

Не забудьте убить слушателей событий в componentWillUnmount (), чтобы предотвратить утечки памяти.

0 голосов
/ 04 февраля 2019

Для этого вам просто нужно добавить следующий код

$(document).on('scroll', function() {
    if($(document).height() - $(document).scrollTop() - $(window).height() < 50) {
        this.fetchMoreData();
    }
});

Вот ссылка на рабочий Скрипка .

Конечно, вы должны заменить50 с желаемым расстоянием.

...