Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
608 views
in Technique[技术] by (71.8m points)

javascript - react一次只显示n个产品,其余的保持闲置状态,滚动到页面底部时再显示n个产品(react Only show n number of products at a time keep the rest in idle and show another n number when scroll to bottom of page)

I am creating a react app and I want to show only show 21 number of elements at a time and keep the rest in idle and show another 21 elements when scroll to bottom of page.(我正在创建一个React应用,我想一次只显示21个元素,其余的保持闲置,滚动到页面底部时再显示21个元素。)

I have my component that gets the products and insets an add every 20 products.(我有我的组件来获取产品,并每20个产品插入一个添加项。)

I want to only show 21 elements at a time (20 products and 1 add) while keeping the rest idle to load another 21 elements when they scroll down.(我想一次只显示21个元素(20个产品和1个添加项),同时让其余的元素闲置以在向下滚动时加载另外21个元素。) Is there a way to pre-emptively fetch the next batch of results in advance and keep them idle till they need displaying (when user reaches end of the last bach of results).(有没有一种方法可以预先抢先获取下一批结果,并使它们保持空闲状态直到需要显示(当用户到达最后一个结果末尾时)。)

this is my component(这是我的组成部分)

        import React from "react";
import { Loading } from "./LoadingComponent";

const axios = require('axios');

class Products extends React.Component {


  constructor(props){
        super(props);
        this.state = {
      displayedList : [],
      indexDisplayed : 0,
      isLoading: false,
      error: null
    }
    }



  _injectAdsInList = list => {
    // an array of your ads

    this.setState({ isLoading: false });
    const AdsList = ['111','2222'];

    if (Array.isArray(list)) {
      const insertAdAt = 21;
      const productsAndAdsList = list.map((item, index) => {
        // not sure about this calculation
        // but this should be done here
        if (index % insertAdAt === 0 && index !== 0) {
          // its the 20th item insert an ad
          return AdsList[0];
        }

        // otherwise insert the item
        return item;
      });

      this.setState({ productsAndAdsList });
    }
  };





  _getProducts = () => {

    this.setState({ isLoading: true });
    // make the fetch call
    // use axios (https://www.npmjs.com/package/axios)
    // for making http requests
    axios.get('http://localhost:3000/products').then(list => this._injectAdsInList(list.data))
      .catch(error => this.setState({ error, isLoading: false }));
  };

  _addToDisplay = ()=> {

    let displayedList = this.state.displayedList;
    let indexDisplayed = this.state.displayedList;
    let productsAndAdsList = this.state.displayedList;
        for(let i = indexDisplayed + 1; i <= indexDisplayed + 21; i++ ){
            displayedList.push(productsAndAdsList[i]);
        }

        this.setState({
            indexDisplayed  : this.state.indexDisplayed+21, 
            displayedList : displayedList
        });
    }


  _sortPrice = () => {
    const { productsAndAdsList } = this.state;
    // instead of mutating the origin array
    // create a new one, and update the state
    const sortedProducts = productsAndAdsList.sort((a, b) => a.price - b.price);
    this.setState({ productsAndAdsList: sortedProducts });
  };

  _sortSize = () => {
    const { productsAndAdsList } = this.state;
    // instead of mutating the origin array
    // create a new one, and update the state
    const sortedProducts = productsAndAdsList.sort((a, b) => a.size - b.size);
    this.setState({ productsAndAdsList: sortedProducts });
  };

  _sortId = () => {
    const { productsAndAdsList } = this.state;  
    const sortedProducts =  productsAndAdsList.sort((a, b) => {
  if (a.id < b.id)
    return -1;
  if (a.id > b.id)
    return 1;
  return 0;
});
    this.setState({ productsAndAdsList: sortedProducts });
  }

   _timeAgo = (prevDate) => {
        const diff = Number(new Date()) - prevDate;
        const minute = 60 * 1000;
        const hour = minute * 60;
        const day = hour * 24;
        const month = day * 30;
        const year = day * 365;
        switch (true) {
            case diff < minute:
                const seconds = Math.round(diff / 1000);
                 return `${seconds} ${seconds > 1 ? 'seconds' : 'second'} ago`
            case diff < hour:
                return Math.round(diff / minute) + ' minutes ago';
            case diff < day:
                return Math.round(diff / hour) + ' hours ago';
            case diff < month:
                return Math.round(diff / day) + ' days ago';
            case diff < year:
                return Math.round(diff / month) + ' months ago';
            case diff > year:
                return Math.round(diff / year) + ' years ago';
            default:
                return "";
        }
    };

  componentDidMount() {
    // I personally prefer not to make any
    // http calls directly in componentDidMount
    // instead, creating a new function makes sense
    this._getProducts();
  }

  render() {

    const { isLoading, hasError } = this.state;

console.log(this._addToDisplay());

    // show spinner
    if (!hasError && isLoading) {
      return <Loading />;
    }

    // show error
    if (hasError && !isLoading) {
      return <p>error.message</p>;
    }

    return (
      <div>
       <div className="row">
            <div className="col-12">
                <button onClick={this._sortPrice}>sort by price lower to higher</button>
                <button onClick={this._sortSize}>sort by size small to big</button>
                <button onClick={this._sortId}>sort by Id</button>  
            </div>  
        </div>
        { this.state.displayedList.map(item => { return (
                        <div className="row">
              <div className="col-4">
                <p> Price: ${(item.price / 100).toFixed(2)}</p>
              </div>

              <div className="col-4">
                <p style={{ fontSize: `${item.size}px` }}> {item.face}</p>
              </div>
            <div className="col-3">
                  <p>Published: {this._timeAgo(new Date(item.date).getTime())}</p>
                </div>
            </div>
            ) } )

                }

          <button onClick={this._addToDisplay()}>Load 21 MORE</button>

       <div className="row">
            <div className="col-12">
                <p>END OF CATALOG</p>  
            </div>  
        </div>
      </div>
    );
  }
}

export default Products;
  ask by Natasha translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Store the result in a variable and each time you want to display more call the addToDisplay function.(将结果存储在变量中,每次要显示更多结果时,请调用addToDisplay函数。)

In the render, use the displayedList .(在渲染中,使用displayedList 。)

I made a simplier version of your code to explain my words so you can implement the solutions the way you want in your code(我制作了一个简单的代码版本来解释我的文字,以便您可以按照自己的方式在代码中实现解决方案)

I assume that you will find a way to trigger addToDisplay as your issue was not about how to trigger a function when you scroll down.(我假设您将找到一种触发addToDisplay的方法,因为您的问题不在于向下滚动时如何触发函数。)

class MyComponent extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            list : [],
            displayedList : [],
            indexDisplayed : 0
        }
    }

    componentDidMount(){
      this.loadData();
    }

    loadData = ()=> {

        axios.get('http://localhost:3000/products').then(list => {
            this.setState({list : list});
            this.addToDisplay();
        });
    }


    addToDisplay = ()=> {
        let displayedList = this.state.displayedList;
        for(let i = indexDisplayed + 1; i <= indexDisplayed + 21; i++ ){
            displayedList.push(list[i]);
        }

        this.setState({
            indexDisplayed  : this.state.indexDisplayed+21, 
            displayedList : displayedList
        });
    }

    render(){
        return(
            <div>
                // use this.state.displayedList to display your elements
                {
                    this.state.displayedList.map(item => {
                        // the way you want to display your item
                    })
                }

                <button onClick={this.addToDisplay}>Load 21 MORE</button>
            </div>
        )

    }


}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...