reactjs和mongoose无限滚动实现问题

问题描述 投票:0回答:1

最终结果需要排序并在结果顶部显示“reach-up-ads”,并且在滚动窗口而不单击按钮时获取更多结果。我刚刚添加了“加载更多”按钮进行测试。

现有实现不会在结果顶部显示“reach-up-ads”,并且在单击“加载更多”按钮时两次加载相同的数据。

前端

  useEffect(()=>{
    fetchPosts();
  }, [skip])

 const loadMore = () => {
   setSkip(posts?.length);
 }

const fetchPosts = async () => {
        const { data } = await getMobilePosts(skip);
        const filterData = await data?.filter(obj => obj.adPromote == "free-ad" || obj.adPromote == "reach-up-ad")
        .sort((f,p)=>{
            if (f.adPromote === 'reach-up-ad' && p.adPromote !== 'reach-up-ad') {
                return -1;
              } else if (f.adPromote !== 'reach-up-ad' && f.adPromote === 'reach-up-ad') {
                return 1;
              }
            return 0;
        })
        .map(obj => {
            return {
                ...obj,
                title: `${obj.title} (${obj.features.condition})`,
                location: `Posted On ${new Date(obj.createdAt).toDateString()}
            }
        });
   setPosts(existing => [...existing, ...filterData]);
}

    return (
        <div>
          {posts?.map((data, i) => {
                                return (
                                    <ExchangeItemWideCard
                                    key={i}
                                    id={data._id}
                                    title={data.title}
                                    location={data.location}
                                    />
                                )
          })}
        <Button onClick={loadMore}>Load more</Button>
        </div>
   )

猫鼬

    export async function getMobilePosts(skips: any) {
          try{
            const skip = skips ? Number(skips) : 0;
            const DEFAULT_LIMIT = 10;
            return await Post.find({expiredAt: {$gte: currentDate},status: 'live'},
                                    "features.subCategory features.condition swapType.type swapType.price createdAt features.mainCategory title location.district location.location photos adPromote status description postedBy notes")
                                    .skip(skip)
                                    .limit(DEFAULT_LIMIT)
                                    .sort({ _id: -1 });
          } catch(error: any) {
            throw new Error(error as any);
          }
   }
node.js reactjs mongoose infinite-scroll
1个回答
0
投票

我找到了这个简单的解决方案,无需使用任何 NPM 包。

信息

场景是这样的,当用户滚动到选定的 div 区域时,仅从后端 mongoDB 数据库获取数据,然后用户滚动应该获取更多数据。我使用

IntersectionObserver
useRef
来确定 div 位置,然后使用
addEventListener
设置滚动事件。最终代码如下所示。

      const [post, setPost] = useState([]);
      const [skip, setSkip] = useState(0);
      const [loadMore, setLoadMore] = useState(true);
      const [scrolled, setScrolled]:any = useState();
    
      const endRef = useRef();

      useEffect(() => {
        getData(loadMore);
        setLoadMore(false);
      }, [scrolled]);

      useEffect(() => {
        //user being scrolled to list section
        const observer = new IntersectionObserver((entries) => {
        const entry = entries[0];
        setScrolled(entry.isIntersecting)
      })
      observer.observe(endRef.current)

      const list = document.getElementById('list')
      if(props.scrollable) {
         // get list div properties if div is fixed height
        list.addEventListener('scroll', (e) => {
        const el = e.target; //documentElement
        if(el.scrollTop + el.clientHeight === el.scrollHeight) {
           setLoadMore(true);
        }
      });
      } else {
        // list has auto height
        window.addEventListener('scroll', () => {
       //now scrolling + browser height === list div height + if any indent of top of the page
       if (window.scrollY + window.innerHeight === list.clientHeight + list.offsetTop) {
            setLoadMore(true);
          }
        });
      }
       return () => {
        window.removeEventListener('scroll', this);
       }
     }, []);

     useEffect(() => {
      const list = document.getElementById('list');
      if(list.clientHeight <= window.innerHeight && list.clientHeight) {
        setLoadMore(true);
      }
   }, [post]);

   

    const getData = async (load) => {
        if(load){
           //fetch data from back-end
        }
    }

  return (
    <div id='list' style={{maxHeight: '30%'}} ref={endRef}>
      {post?.map((data, i) => {})}
    </div>
   )
© www.soinside.com 2019 - 2024. All rights reserved.