Javascript Reactjs Redux:具有多个不同GET请求的无限滚动

Javascript Reactjs Redux:具有多个不同GET请求的无限滚动,javascript,reactjs,redux,axios,window-scroll,Javascript,Reactjs,Redux,Axios,Window Scroll,我在reactjs中构建了一个无限滚动,当用户点击页面底部时,数据从同一个API加载。现在,这里的问题是从多个不同的API获取数据以获取其他数据。那么,实现这一点的正确方法是什么呢?请帮我解决这个问题。这是我的代码 import React from "react"; import { Link } from 'react-router-dom'; import axios from 'axios'; const BUSY = {}; class InfiniteData extends Re

我在reactjs中构建了一个无限滚动,当用户点击页面底部时,数据从同一个API加载。现在,这里的问题是从多个不同的API获取数据以获取其他数据。那么,实现这一点的正确方法是什么呢?请帮我解决这个问题。这是我的代码

import React from "react";
import { Link } from 'react-router-dom';
import axios from 'axios';
const BUSY = {};

class InfiniteData extends React.Component{

constructor(props){
super(props);
this.state={
  olddata: [],
  newData: [],
  requestSent: false,
  scrollCounter:1
  }
  this.handleOnScroll = this.handleOnScroll.bind(this)
  this.buildData = this.buildData.bind(this)
}

componentDidMount(){
  window.addEventListener('scroll', this.handleOnScroll);
  this.doQuery(1).then(res=>
    this.setState({
     newData: this.state.newData.slice().concat(res),
    requestSent: false
  }))
}

componentWillUnmount() {
  window.removeEventListener('scroll', this.handleOnScroll);
}
queryActive = false;
doQuery(queryParam) {
  if(this.queryActive){
    return Promise.resolve(BUSY);
  }
  this.queryActive=true;
  switch(queryParam){
    case 1: return this.buildData(queryParam).then((res)=>res).catch(err=>{})
    break;
    case 2: return this.buildData(queryParam).then((res)=>res);
    break;
    case 3: return this.buildData(queryParam).then((res)=>res);
    break;
    case 4: return this.buildData(queryParam).then((res)=>res);
    break;
    default: return true;
  }

}

buildData(queryParam){
  //there is no paging in getting posts, won't it just get the same posts?
  return axios.get("https://jsonplaceholder.typicode.com/posts")
  .then( res=> {this.queryActive=false;return res.data;})
  .catch(err=>{
    this.queryActive=false;
    return Promise.reject(err);
  })
}


handleOnScroll(){
  var scrollCounter=0;
  var scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
  var scrollHeight = (document.documentElement && document.documentElement.scrollHeight) || document.body.scrollHeight;
  var clientHeight = document.documentElement.clientHeight || window.innerHeight;
  var scrolledToBottom = Math.ceil(scrollTop + clientHeight) >= scrollHeight;
  if (scrolledToBottom) {
    this.setState({
      scrollCounter: this.state.scrollCounter + Math.floor(scrolledToBottom)
    })
    if(this.state.scrollCounter<5){
      this.doQuery(this.state.scrollCounter).then(res=>
      (res===BUSY)
        ? false
        : this.setState({
            newData: this.state.newData.slice().concat(res)
          })
        )
        .catch(err=>this.setState({requestSent: false}))
        this.setState({requestSent: true});
    }else{
      return true
    }

  }
}

  render()
  {
    return (
    <div>
      <div className="data-container">
      <div  className="row ">
        {this.state.newData && this.state.newData.map((dat,i)=>
          <div key={i} className="col-lg-4">
              <div className="bordered">
                {dat.body}
              </div>
            </div>
        )}
          </div>
      </div>
    </div>
    );
  }
}

export default InfiniteData;
从“React”导入React;
从'react router dom'导入{Link};
从“axios”导入axios;
const BUSY={};
类InfiniteData扩展了React.Component{
建造师(道具){
超级(道具);
这个州={
旧数据:[],
新数据:[],
请求发送:false,
滚动计数器:1
}
this.handleOnScroll=this.handleOnScroll.bind(this)
this.buildData=this.buildData.bind(this)
}
componentDidMount(){
window.addEventListener('scroll',this.handleOnScroll);
this.doQuery(1).then(res=>
这是我的国家({
newData:this.state.newData.slice().concat(res),
请求发送:false
}))
}
组件将卸载(){
window.removeEventListener('scroll',this.handleOnScroll);
}
queryActive=false;
doQuery(查询参数){
if(this.queryActive){
回报承诺。解决(忙);
}
this.queryActive=true;
开关(queryParam){
案例1:返回这个.buildData(queryParam).then((res)=>res.catch(err=>{})
打破
案例2:返回这个.buildData(queryParam)。然后((res)=>res);
打破
案例3:返回这个.buildData(queryParam)。然后((res)=>res);
打破
案例4:返回这个.buildData(queryParam)。然后((res)=>res);
打破
默认值:返回true;
}
}
buildData(查询参数){
//在获取帖子时没有分页功能,它不只是获取相同的帖子吗?
返回axios.get(“https://jsonplaceholder.typicode.com/posts")
.then(res=>{this.queryActive=false;返回res.data;})
.catch(错误=>{
this.queryActive=false;
退回承诺。拒绝(错误);
})
}
手卷{
var scrollCounter=0;
var scrollTop=(document.documentElement&&document.documentElement.scrollTop)| document.body.scrollTop;
var scrollHeight=(document.documentElement&&document.documentElement.scrollHeight)| document.body.scrollHeight;
var clientHeight=document.documentElement.clientHeight | | window.innerHeight;
var scrolledToBottom=Math.ceil(scrollTop+clientHeight)>=scrollHeight;
如果(滚动到工具栏){
这是我的国家({
scrollCounter:this.state.scrollCounter+Math.floor(scrolledToBottom)
})
if(this.state.scrollCounter
(res==忙)
?错误
:this.setState({
newData:this.state.newData.slice().concat(res)
})
)
.catch(err=>this.setState({requestSent:false}))
this.setState({requestSent:true});
}否则{
返回真值
}
}
}
render()
{
返回(
{this.state.newData&&this.state.newData.map((dat,i)=>
{dat.body}
)}
);
}
}
导出默认无限数据;

您可以添加一个名为BUSY的常量,当doQuery正在忙于发出请求时,doQuery将其用作返回值:

import React from "react";
import { Link } from 'react-router-dom';
import axios from 'axios';
const BUSY = {};
您可以对doQuery进行一些更改:

queryActive = false;
doQuery() {
  if(this.queryActive){
    return Promise.resolve(BUSY);
  }
  this.queryActive=true;
  //there is no paging in getting posts, won't it just get the same posts?
  return axios.get("https://jsonplaceholder.typicode.com/posts")
  .then( res=> {this.queryActive=false;return res.data;})
  .catch(err=>{
    //before you were only console.logging the error but that causes you
    //  to create a promise that doesn't reject but resolves with undefined
    //  when something goes wrong
    this.queryActive=false;
    console.warn(err);
    return Promise.reject(err);
  })
}
调用doQuery时,如果结果繁忙,请确保忽略结果:

this.doQuery().then(res=>
  (res===BUSY)
    ? false
    : this.setState({
        newData: this.state.newData.slice().concat(res)
      })
)
.catch(err=>this.setState({requestSent: false}))
this.setState({requestSent: true});

我打赌
doQuery
函数应该负责从各种API获取数据;您可以向它传递参数以控制从哪个API获取。我认为这是朝着你的目标迈出的有效的下一小步。还有什么东西阻碍或限制你这么做吗?旁注:
Array#concat
是非破坏性的,因此无需在它前面加上
Array#slice
。您可以在doQuery中创建一个async/wait函数,将多个请求发送到不同的api,并将结果附加到state。代码的问题是您发出相同的请求,没有分页?第二个问题是,假设数据的解析顺序与请求的解析顺序相同,但事实并非如此。您可以发出请求1,2,3,但按顺序1,3,2获得结果。您可以在doQuery处于活动状态时不调用doQuery来处理此问题。@RishatMuhametshin您的意思是,将scrollbottom值的计数作为参数传递给
doQuery()
。然后根据参数切换axios get请求?请帮我更新代码。请检查。谢谢,@HMR您能告诉我如何在
doquery
中发出各种API请求以获得不同的帖子/数据吗。@karthik您使用的是一个模拟json rest API,因此您只需添加
\u page
\u limit
之类的内容:最好多索取一个,这样您就知道需要获得更多。如果serer返回的值小于您要求的值,则没有更多记录可显示。