1.3.1 • Published 3 years ago

react-observer-infinite-scroll v1.3.1

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

react-observer-infinite-scroll

一个基于 IntersectionObserver 的无限滚动 react-hook 组件,支持正向滚动、逆向滚动(类似微信聊天回滚加载历史数据)、滑到底部

install

npm install --save react-observer-infinite-scroll

// in code ES6
import InfiniteScroll from 'react-observer-infinite-scroll';

demos

ScrolleableTop

类似聊天查看历史记录倒序无限加载

import React, { useRef, useState, useCallback } from 'react';
import InfiniteScroll, { InfiniteScrollOutRef } from 'react-observer-infinite-scroll';

const ScrolleableTop = () => {
  const targetRef = useRef<InfiniteScrollOutRef>(null);
  const targetWrapRef = useRef(null);
  const [list, setList] = useState(Array.from({ length: 20 }));
  const [loading, setLoading] = useState(false);

  const next = useCallback(() => {
    setLoading(true);
    setTimeout(() => {
      setList(pre => pre.concat(Array.from({ length: 20 })));
      setLoading(false);
    }, 2000);
  }, []);

  const toBottom = useCallback(() => {
    targetRef?.current?.scrollToBottom && targetRef?.current?.scrollToBottom();
  }, [targetRef]);
  return (
    <div
      ref={targetWrapRef}
      style={{
        height: 300,
        overflow: 'auto',
        position: 'relative',
        display: 'flex',
        flexDirection: 'column-reverse',
      }}>
      <button
        onClick={toBottom}
        style={{
          width: 100,
          height: 30,
          right: 30,
          top: 30,
          zIndex: 500,
          position: 'fixed',
        }}>
        TO BOTTOM
      </button>
      <InfiniteScroll
        intersectionOption={{ root: targetWrapRef.current }}
        dataLength={list.length}
        inverse
        next={next}
        loading={loading}
        hasMore={true}
        ref={targetRef}
        loader={<h4>Loading...</h4>}>
        {list.map((_, i) => (
          <div key={i} style={{ height: 30, margin: 4, border: '1px solid hotpink' }}>
            #{i + 1} row
          </div>
        ))}
      </InfiniteScroll>
    </div>
  );
};
export default ScrolleableTop;

WindowInfiniteScrollComponent

常用的基于 全局 Windows 的无限下拉

import { useState } from 'react';
import InfiniteScroll from 'react-observer-infinite-scroll';

const WindowInfiniteScrollComponent = () => {
  const [data, setData] = useState(Array.from({ length: 20 }));
  const [loading, setLoading] = useState(false);
  const next = () => {
    setLoading(true);
    setTimeout(() => {
      setData(pre => pre.concat(Array.from({ length: 20 })));
      setLoading(false);
    }, 2000);
  };
  return (
    <>
      <InfiniteScroll
        loading={loading}
        hasMore={true}
        next={next}
        loader={<h1>Loading...</h1>}
        dataLength={data.length}>
        {data.map((_, i) => (
          <div key={i} style={{ height: 30, margin: 4, border: '1px solid hotpink' }}>
            #{i + 1} row
          </div>
        ))}
      </InfiniteScroll>
    </>
  );
};

export default WindowInfiniteScrollComponent;

ScrolleableBottom

常用的基于 容器 Element 的无限下拉

import React, { useRef, useState, useCallback } from 'react';
import InfiniteScroll, { InfiniteScrollOutRef } from 'react-observer-infinite-scroll';

const ScrolleableBottom = () => {
  const targetRef = useRef<InfiniteScrollOutRef>(null);
  const targetWrapRef = useRef(null);
  const [list, setList] = useState(Array.from({ length: 20 }));
  const [loading, setLoading] = useState(false);

  const next = useCallback(() => {
    setLoading(true);
    setTimeout(() => {
      setList(pre => pre.concat(Array.from({ length: 20 })));
      setLoading(false);
    }, 2000);
  }, []);

  const toBottom = useCallback(() => {
    targetRef?.current?.scrollToBottom && targetRef?.current?.scrollToBottom();
  }, [targetRef]);
  return (
    <div
      ref={targetWrapRef}
      style={{
        height: 300,
        overflow: 'auto',
        position: 'relative',
      }}>
      <button
        onClick={toBottom}
        style={{
          width: 100,
          height: 30,
          right: 30,
          top: 30,
          zIndex: 500,
          position: 'fixed',
        }}>
        TO BOTTOM
      </button>
      <InfiniteScroll
        intersectionOption={{ root: targetWrapRef.current }}
        dataLength={list.length}
        next={next}
        loading={loading}
        hasMore={true}
        ref={targetRef}
        loader={<h4>Loading...</h4>}>
        {list.map((_, i) => (
          <div key={i} style={{ height: 30, margin: 4, border: '1px solid hotpink' }}>
            #{i + 1} row
          </div>
        ))}
      </InfiniteScroll>
    </div>
  );
};

export default ScrolleableBottom;

props

nametypedescription
nextfunction触发滚动的回调函数
loadingboolean控制内部 loading 显示状态
hasMoreboolean是否可以加载更多
childrennode (list)滚动列表子级元素
loadernode加载动画元素
styleobject容器样式表
intersectionOptionobjectIntersectionObserver 参数
inverseboolean是否倒序
dataLengthnumber滚动列表数据数组的 length