【问题标题】:Infinite Scrolling not working in the react when api is called调用api时无限滚动在反应中不起作用
【发布时间】:2021-08-11 11:33:36
【问题描述】:

我正在为我的 Web 应用程序使用 react-redux 环境,但我无法进行无限滚动,一旦我到达底部,就会收到无法使用 useEffect 的错误。下面是代码:

import React, { useEffect } from 'react';
import './Homefeed.css';
import StickyNav from '../StickyNav/StickyNav';
import { fetchHomePosts } from '../Redux/HomeFeed-Redux/HomeFeedActionMethods';
import { connect } from 'react-redux';
import PostCell from '../PostCell/PostCell';
import InfiniteScroll from 'react-infinite-scroll-component';
import { useDispatch } from 'react-redux'



function Homefeed({homeposts,fetchHomePosts}) {

    var skipper = 0;
    
    let dispatch = useDispatch()

    useEffect(()=>{fetchHomePosts(skipper);},[dispatch]);
  
    
   

    function MorePosts(){
        console.log(homeposts);
        console.log("more");
        useEffect(()=>{fetchHomePosts(skipper+10);},[]);
  
    }
    

    return homeposts.isLoading ? (<h2>Loading...</h2>) : homeposts.error ? (<h3>{homeposts.error}</h3>) : (


            <div className="homefeed-layout">
                <title>Home Feed</title>
                <StickyNav />
                <InfiniteScroll
                    dataLength={homeposts.homeposts.length}
                    hasMore={true}
                    loader={<h3>Loading</h3>}
                    next={()=>{MorePosts()}}                                                             
                    >
                    {
                        homeposts.homeposts?.map((key,index)=> {
                            

                            var slug = key.attributes.title;
                                slug = slug.replace(/\s/g, '-');
                                slug = slug.toLowerCase();
                                slug = slug.replace(/[^a-zA-Z0-9\-]/g, '');
                                slug = slug.replace(/(-)\1+/g, '-');
                                slug = slug.replace(/-$/, '');
                                slug = slug.replace(/^-/, '');

                            return( 
                                    <div className="content-area" key={index} >
                                        
                                        <PostCell
                                             key ={index}
                                             slug = {slug}
                                             postId = {key.id}
                                             title ={key.attributes.title}
                                             likes ={key.attributes.likes}
                                             comments ={key.attributes.comments}
                                             category ={key.attributes.category}
                                             postimageurl = {key.attributes.postImageURL}
                                             handle ={key.attributes.createdBy.attributes.handle}
                                             timestamp = {key.attributes.createdAt}
                                             subtitle = {key.attributes.subtitle}
                                             realName ={key.attributes.createdBy.attributes.realName}
                                             profileImage = {key.attributes.createdBy.attributes.profileImage?._url}
                                             followers = {key.attributes.createdBy.attributes.followers}
                                             posts = {key.attributes.createdBy.attributes.posts}
                                             name = {key.attributes.createdBy.attributes.name}
                                        />
                                        

                                    </div>
                            )
                        })
                    }
                </InfiniteScroll>


            </div>
            
            
            
        )
}

const mapStatetoProps = (state) =>{
    return{
        homeposts:state.HomePosts
    }
}

const mapDispatchtoProps = (dispatch) =>{
    return{
        fetchHomePosts:(skipper)=>{dispatch(fetchHomePosts(skipper))},dispatch,
    }
}

export default connect(mapStatetoProps,mapDispatchtoProps) (Homefeed)

所以这里无限滚动中的下一个道具应该调用更多应该附加到现有数据的数据。 moreposts 函数应该调用 api,但是 react 给我一个错误,说你不能在这个函数中调用 useEffect。

如果我使用 useDispatch(),它会陷入无限循环,有人可以帮帮我吗,我对此很陌生。

【问题讨论】:

    标签: reactjs react-redux infinite-scroll


    【解决方案1】:

    你不能在另一个函数内部调用useEffect,因为这违反了钩子的规则。但是useEffect 在这里没有做任何事情。您可以直接从morePosts() 拨打fetchHomePosts(skipper+10)

    这将加载第二页。如果要加载第三个和第四个等等,则需要将skipper 设置为状态而不是var。每次加载页面时将10 添加到skipper

    您可以:

    • 增加skipper 并在您的morePosts() 函数中调用fetchHomePosts()
    • 在您的morePosts() 函数中增加skipper 并从useEffect 挂钩中调用fetchHomePosts(),该挂钩将skipper 作为依赖项,以便每当skipper 的值发生变化时效果都会运行。
    • 将最后获取的页码保存在您的 Redux 存储中。
    • 偏移量基于homePosts 数组的长度。

    您不需要使用useDispatch connect。它们是做同一件事的两种方式,因此您应该使用其中一种。钩子是推荐的方法。

    这并不完美,但我不想让事情变得过于复杂:

    export default function Homefeed() {
      const homeposts = useSelector((state) => state.HomePosts);
      const dispatch = useDispatch();
    
      // want to make sure that the first page is loaded when the component mounts
      useEffect(() => {
        dispatch(fetchHomePosts(0));
      }, [dispatch]);
    
      // starts at 0 and increases when more posts load
      const dataLength = homeposts.homeposts.length;
    
      // function to load the next page
      const morePosts = () => {
        dispatch(fetchHomePosts(dataLength));
      };
    
      return homeposts.isLoading ? (
        <h2>Loading...</h2>
      ) : homeposts.error ? (
        <h3>{homeposts.error}</h3>
      ) : (
        <div className="homefeed-layout">
          <title>Home Feed</title>
          <StickyNav />
          <InfiniteScroll
            dataLength={dataLength}
            hasMore={true}
            loader={<h3>Loading</h3>}
            next={morePosts}
          >
            {homeposts.homeposts?.map((key, index) => {
              // I would store this slug in Redux when you store the post
              const slug = key.attributes.title
                .replace(/\s/g, "-")
                .toLowerCase()
                .replace(/[^a-zA-Z0-9-]/g, "")
                .replace(/(-)\1+/g, "-")
                .replace(/-$/, "")
                .replace(/^-/, "");
    
              return (
                <div className="content-area" key={index}>
                  <PostCell
                    key={index}
                    slug={slug}
                    postId={key.id}
                    title={key.attributes.title}
                    likes={key.attributes.likes}
                    comments={key.attributes.comments}
                    category={key.attributes.category}
                    postimageurl={key.attributes.postImageURL}
                    handle={key.attributes.createdBy.attributes.handle}
                    timestamp={key.attributes.createdAt}
                    subtitle={key.attributes.subtitle}
                    realName={key.attributes.createdBy.attributes.realName}
                    profileImage={
                      key.attributes.createdBy.attributes.profileImage?._url
                    }
                    followers={key.attributes.createdBy.attributes.followers}
                    posts={key.attributes.createdBy.attributes.posts}
                    name={key.attributes.createdBy.attributes.name}
                  />
                </div>
              );
            })}
          </InfiniteScroll>
        </div>
      );
    }
    

    【讨论】:

    • 非常感谢!!这正是我想要的。但我发现在应用程序的这一部分我不需要 redux,所以我将函数转换为一个类并使用状态。但这真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多