ReactPullToRefreshify: 一个极简的React下拉刷新库

1,205 阅读2分钟

引言

在前端开发中,下拉刷新是一项非常常见的功能。

虽然现在 React 有很多库可以实现这个功能,但它们存在着一些问题:

  • 大多数带有下拉刷新功能的组件都是UI库,因此在引入下拉刷新组件后,往往需要引入整个UI库,会增加许多不必要的依赖。
  • 这些库中大部分的自定义程度都很低,如果想要自定义下拉动画效果,会非常麻烦。
  • 需要对下拉容器设置高度,无法利用父容器的滚动。

为了解决上述问题,ReactPullToRefreshify 诞生了

优点

ReactPullToRefreshify它有以下优点👇:

  1. 这是一个极简的React下拉刷新组件,不依赖于其他库。
  2. 它的 API 设计与 Ant Design Mobile 相似,可定制化程度更高
  3. 而且压缩后的文件大小只有2kb,适用于手机端和电脑端。

安装

那下面让我们来看看怎么安装使用吧!👀

$ npm i react-pull-to-refreshify
# or
$ yarn add react-pull-to-refreshify

基础使用

import { PullToRefreshify } from "react-pull-to-refreshify";

function renderText(pullStatus, percent) {
  switch (pullStatus) {
    case "pulling":
      return (
        <div>
          {`下拉即可刷新 `}
          <span style={{ color: "green" }}>{`${percent.toFixed(0)}%`}</span>
        </div>
      );

    case "canRelease":
      return "释放即可刷新...";

    case "refreshing":
      return "刷新中";

    case "complete":
      return "刷新成功";

    default:
      return "";
  }
}

const [refreshing, setRefreshing] = useState(false);

function handleRefresh() {
  setRefreshing(true);
  setTimeout(() => {
    setRefreshing(false);
  }, 2000);
}

<PullToRefreshify
  refreshing={refreshing}
  onRefresh={handleRefresh}
  renderText={renderText}
>
  {list.map((item, i) => (
    <div key={item.id}>{item}</div>
  ))}
</PullToRefreshify>;

自定义动画效果

动画效果1

动画效果2

加载更多

上拉加载

小伙伴们可能关心另一件事情,那么这个组件支不支持上拉加载更多功能呢?

为了尽可能地保持小而精,这个库本身是不支持上拉加载更多的功能。

但你可以很容易地和 react-intersection-observer 结合去实现上拉加载功能,让专业人去做专业的事。

下面我们可以简单地看看如何利用 react-intersection-observer 的 useInView 去实现上拉加载更多功能。

在线预览地址 codesandbox.io/s/mystifyin…

import { useInView } from "react-intersection-observer";

// 指示器是否在视图内
const { ref, inView } = useInView();
// 是否在加载下一页
const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);
// 模拟列表数据长度
const [dataLength, setDataLength] = useState(20);
// 是否有下一页,模拟数据最大为60
const hasNextPage = dataLength < 60;

// 模拟请求更多数据
const loadMore = useCallback(() => {
  if (
    // 指示器出现在视图内
    inView &&
    // 存在下一页
    hasNextPage &&
    // 没有在请求中
    !isFetchingNextPage
  ) {
    setIsFetchingNextPage(true);
    setTimeout(() => {
      setDataLength((prev) => prev + 20);
      setIsFetchingNextPage(false);
    }, 2000);
  }
}, [inView, hasNextPage, isFetchingNextPage]);

// 自动加载下一页数据
useEffect(() => {
  loadMore();
}, [loadMore]);


<PullToRefreshify
  refreshing={refreshing}
  onRefresh={handleRefresh}
  renderText={renderText}
>
  {Array.from({ length: dataLength }).map((item, i) => (
    <div key={item.id}>{item}</div>
  ))}

  {/* 加载更多指示器 */}
  <button ref={ref} onClick={loadMore}>
    {isFetchingNextPage
      ? "加载更多..."
      : hasNextPage
      ? "点击加载下一页"
      : "已经到底了~"}
  </button>
</PullToRefreshify>;

在线预览地址

竞品对比

ReactPullToRefreshifyAntDesignMobile PullToRefreshReactSimplePullToRefresh
下拉百分比动画🛑🛑
拉动难度🛑
上拉加载🛑🛑
打包体积2.07kb188kb2.42kb

Github

如果你想要了解更多有关实现的信息,请点击下面的链接查看

github.com/HuolalaTech…