前言
前面我们已经封装了懒加载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组件封装】。关注本栏目,将实时更新。