React+TS前台项目实战(十八)-- 全局常用高阶渲染劫持组件封装

发布于:2024-06-28 ⋅ 阅读:(15) ⋅ 点赞:(0)


前言

前面我们已经封装了懒加载Loading组件,可自行查阅具体代码及说明 响应式加载动画Loading组件封装。本文我们就结合使用Loading组件,来封装一个高阶组件。


QueryResult组件

1. 功能分析

(1)用于处理查询结果,根据查询的状态来渲染不同的组件,可以称之为高阶渲染劫持组件
(2)使用useDelayLoading延迟加载函数,根据delayLoading参数决定是否延迟加载
(3)如果查询出错,QueryResult组件会渲染错误组件或默认的错误组件
(4)如果查询成功,QueryResult组件会渲染子组件,并传入查询结果
(5)如果查询正在加载,QueryResult组件会渲染加载组件,并根据delayLoading参数决定是否延迟加载

2. 代码+详细注释

(1)首先,我们来封装一个默认Error组件

// @/components/QueryResult/Error/index.tsx
import notFound from "./notFound.png";
import { useIsMobile } from "@/hooks";
import { ErrorPanel } from "./styled";
import classNames from "classnames";

// 数据未找到页面
export default () => {
  const isMobile = useIsMobile(); // 判断是否是移动端
  return (
    <ErrorPanel>
      {/* 数据未找到图片 */}
      <img
        alt="数据未找到" // 图片描述
        className={classNames(isMobile && "mobile-not-found")} // 根据是否是移动端添加不同的样式类
        src={notFound} // 图片地址
      />
    </ErrorPanel>
  );
};
------------------------------------------------------------------------------
// @/components/QueryResult/Error/styled.tsx
import styled from "styled-components";
import variables from "@/styles/variables.module.scss";

export const ErrorPanel = styled.div`
  width: 100%;
  margin: 112px 0 203px;
  text-align: center;

  @media (max-width: ${variables.mobileBreakPoint}) {
    margin: 120px 0 130px;
  }

  > img {
    width: 1038px;
    max-width: 100%;
    margin: 0 auto;

    @media (max-width: ${variables.mobileBreakPoint}) {
      width: 282px;
      height: 130px;
    }
  }
`;

(2)开始来封装渲染劫持组件

// @/components/QueryResult/index.tsx
import { ReactElement } from "react";
import { DefinedUseQueryResult } from "@tanstack/react-query";
import { LOADING_WAITING_TIME } from "@/global/constants/common";
import Error from "./Error";
import Loading from "@/components/Loading";
import { useDelayLoading } from "@/hooks";

/**
 * QueryResult 组件用于处理查询结果。
 * @param query 查询结果
 * @param children 用于渲染查询结果的子组件
 * @param delayLoading 是否延迟加载
 * @param errorRender 错误的渲染函数
 * @param loadingRender 加载的渲染函数
 * @returns ReactElement
 */
export function QueryResult<TData, TError>({
  query,
  children,
  delayLoading,
  errorRender,
  loadingRender,
}: {
  query: DefinedUseQueryResult<TData, TError>;
  children: (data: TData) => ReactElement;
  delayLoading?: boolean;
  errorRender?: (err: TError) => ReactElement;
  loadingRender?: (show: boolean) => ReactElement;
}): ReactElement {
  // 使用 useDelayLoading 延迟加载函数
  const delayedLoading = delayLoading ? useDelayLoading(LOADING_WAITING_TIME, true) : true;
  // 根据查询的状态来渲染不同的组件
  switch (query.status) {
    // 如果查询出错,则渲染错误组件或默认的错误组件
    case "error":
      return errorRender && query.error ? errorRender(query.error) : <Error />;
    // 如果查询成功,则渲染子组件,并传入查询结果
    case "success":
      return children(query.data);
    // 如果查询正在加载,则渲染加载组件,并根据 delayLoading 参数决定是否延迟加载
    case "loading":
    default:
      return loadingRender ? (
        loadingRender(delayedLoading)
      ) : (
        <>
          delayedLoading && <Loading />
        </>
      );
  }
}

3. 使用方式

注:useQuery请求后期搭建页面会教大家使用,这里只是简单讲一下页面怎么使用渲染劫持组件

// 引入组件
import { QueryResult } from '@/components/QueryResult'
// 使用
const dataQuery = useQuery(
  ["list"],
  async () => {
    // 处理请求....
  },
  {
    refetchInterval: 5000,
  }
);
<QueryResult query={ dataQuery } delayLoading>
  {/* ... */}
  {/* 这里放你的模块组件,渲染请求的数据 */}
  {/* ... */}
</QueryResult>

4. 效果展示


总结

下一篇讲【全局常用echarts组件封装】。关注本栏目,将实时更新。


网站公告

今日签到

点亮在社区的每一天
去签到