react项目中封装一个通用的边界Boundary

news2024/11/27 13:39:10

# Boundary 

通用的边界,同时是一个Suspense 和一个 ErrorBoundary

正常情况不直接用,使用一下几个封装好的:

-Boundary.FullSizeLoading: 占满父容器全部高度,居中显示等待动画;

-Boundary.Loading: 占满一行,显示一个普通尺寸的等待动画;

-Boundary.Blank: 什么都不显示,加速速度足够快的话可以使用;

先看一下代码目录结构:

(1)index.tsx 

import {ComponentProps} from 'react';
import {Boundary as SuspenseBoundary,SuspenseBoundaryProps} from 'react-suspense-boundary';
import styled from '@emotion/styled';
import {times} from 'ramda';
import {Spin,Skeletion} from 'antd';
import {flexCenter} from './css/flex';
import fullSizeCenter from './FullSizeCenter/index';
import {defaultRenderError,defaultRenderFullSizeError} from './defaults';

interface Props extends SuspenseBoundaryProps{
    /**
     * 显示错误时是否占满整个容器
     */
    fullSize?:boolean;
}

function Boundary({fullSize =false,...props}:Props){
    return (
        <SuspenseBoundary 
           {...props}
           renderError={props.renderError ?? (fullSize ? defaultRenderFullSizeError : defaultRenderError)}
        />
    )
}

Boundary.FullSizeLoading = function FullSizeLoadingBoundary(props:SuspenseBoundaryProps){
    return (
        <Boundary 
            fullSize
            pendingFallback={
                <fullSizeCenter>
                    <Spin size="large" />
                </fullSizeCenter>
            }
        />
    )
}

export interface SkeletionProps extends SuspenseBoundaryProps,Omit<Components<typeof Skeletion>,'children'>{
    repeat?:number;
}

Boundary.Skeletion = function SkeletionBoundary({repeat=1,...props}:SkeletionProps){
    return (
        <Boundary 
            pendingFallback={
               <div>
                  {times(i => <Skeletion loading active key={i} {...props} />,repeat)}
               </div>
            }
            {...props}
        />
    )
}

Boundary.FullSizeSkeletion = function FullSizeSkeletionBoundary({repeat=1,...props}:SkeletionProps){
    return (
        <Boundary 
            fullSize
            pendingFallback={
                <fullSizeCenter>
                  {times(i => <Skeletion loading active key={i} {...props} />,repeat)}
                </fullSizeCenter>
            }
            {...props}
        />
    )
}

const LoadingContainer =styled.div`
    ${flexCenter};
    margin : 20px 0;
`

Boundary.Loading = function LoadingBoundary(props:SuspenseBoundaryProps){
    return(
        <Boundary 
          pendingFallback={
              <LoadingContainer>
                  <Spin />
              </LoadingContainer>
          }
          {...props}
        />
    )
}

Boundary.InlineLoading = function InlineLoadingBoundary(props:SuspenseBoundaryProps){
    return <Boundary pendingFallback={<Spin size="small" />} {...props} /> 
}

Boundary.Blank = function BlankBoundary(props:SuspenseBoundaryProps){
    return <Boundary pendingFallback={<fullSizeCenter />} {...props} /> 
}

export default Boundary;

 (2)defaults.tsx

inport Error from './Error';
import FullSizeCenter from './FullSizeCenter';

const renderErrorWithFullSize=(fullSize:boolean)=>(error:any)=>{
    const message = error?.message;
    const errorType=error?.responseStatus || '400';
    if(fullSize){
        return (
            <FullSizeCenter>
                <Error type={errorType} message={message} displayInDetail></Error>
            </FullSizeCenter>
        )
    } 
    return   <Error type={errorType} message={message} displayInDetail></Error>
}

export const defaultRenderError = renderErrorWithFullSize(false);
export const defaultRenderFullSizeError = renderErrorWithFullSize(true);

(3)Error/index.tsx

import {createElement} from 'react';
import {useToggle} from '@huse/boolean';
import {Empty,Gap,Button} from 'antd';
import FullSizeCenter from '../FullSizeCenter';
import ServerError from './ServerError.svg?react';
import ClientError from './ClientError.svg?react';
import Forbidden from './Forbidden.svg?react';
import NotFound from './NotFound.svg?react';

const STATUS_CODE_TO_COMPONENT={
    400:ClientError,
    403:Forbidden,
    404:NotFound,
    500:ServerError
};

const GENERAL_ERROR_MESSAGE='请求时出现错误';

const  STATUS_CODE_TO_MESSAGE={
    400:GENERAL_ERROR_MESSAGE,
    403:'无权限',
    404:'找不到指定页面',
    500:'未知的服务端错误',
}

interface Props{
    type?:'500' | '400' | '403' | '404';
    message?:string;
    displayInDetail?:boolean;
    className?:string;
};

export default function Error({type='400',message,displayInDetail,className}:Props){
    const [expand,toggle]=useToggle(false);
    const errorMessage = displayInDetail ? GENERAL_ERROR_MESSAGE : message;
    return (
        <FullSizeCenter style={{flexDirection:'cloumns'}}>
           <Empty 
            image={createElement(STATUS_CODE_TO_COMPONENT[type])}
            description={errorMessage ?? STATUS_CODE_TO_MESSAGE[type]}
            className={className}
           />
           {
               displayInDetail && (
                   <>
                      <Gap.Vertical factor={4} base={4} />
                      <Button type="link" onClick={toggle}>{expand ? '收起' : '查看详情'}</Button>
                      {
                          expand && (
                              <p style={{wordBreak:'break-all'}}>
                                {message}
                              </p>
                          )
                      }

                   <>
               )
           }
        </FullSizeCenter>
    )
}

 (4)FullSizeCenter/index.tsx

import styled from '@emotion/styled';
import fullSizeFlexCenter from '../css/flex';

const fullSizeCenter=styled.div`
${fullSizeFlexCenter}
`
export default fullSizeCenter;

(5)css/flex.ts

import {css} from '@emotion/react';

export const flexCenter =css`
display:flex;
align-items:center;
justify-content:center;
`

export const fullSizeFlexCenter =css`
${flexCenter}
width:100%;
height:100%;
min-height:inherit;
`

使用时,直接用封装好的边界组件来作为顶层组件来包裹其他组件,例如:

<Boundary.Loading >
   ...其他代码
</Boundary.Loading >

代码缺少几个状态码对应的svg,感兴趣的小伙伴自己可以找一下!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1659559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

未来编码探索:揭秘Java的进化之旅与技术革新!

Java是一种广泛使用的编程语言&#xff0c;自1995年问世以来&#xff0c;它在企业级应用、移动应用开发、大数据处理等领域都有着广泛的应用。随着时间的推移&#xff0c;Java也在不断发展和进化&#xff0c;以满足不断变化的技术需求和市场趋势。本文将全面详细地探讨Java的未…

Linux 用户进程启动与Systemd

Linux用户空间的启动 我们都知道&#xff0c;Linux在内核的初始化自身的流程结束后&#xff0c;就会将程序流的运行转到用户态&#xff0c;也就是进入init进程流之后&#xff0c;他会按照这个流程进行初始化&#xff1a; init进程初始化 基础的底层服务&#xff1a;比如说ude…

视频号小店怎么开通优选联盟?开通之后有什么好处?

大家好&#xff0c;我是电商糖果 糖果做视频号小店已经快两年时间了&#xff0c;这期间也一直坚持在网上分享自己做店的经验。 这里糖果就来给大家分享一下&#xff0c;视频号小店怎么开通优选联盟&#xff0c;店铺开通之后会有什么好处&#xff1f; 首先我们要知道优选联盟是…

20240509解决Protel99se导入philips.ddb出现File is not recognized的问题

20240509解决Protel99se导入philips.ddb出现File is not recognized的问题 2024/5/9 16:25 缘起&#xff1a;最近需要用到/画PCB&#xff0c;想到十年前用过Protel99SE。 使用的系统&#xff1a;WIN10/WIN11都会出错。WIN7没有测试&#xff01; 从115网盘的角落里找到七集视频…

Objective-C的对象复制与拷贝选项

对象复制与拷贝 文章目录 对象复制与拷贝copy与mutablecopycopy与mutablecopy的简介示例&#xff1a;不可变对象的复制可变对象的复制 NSCopying和NSMutableCopying协议深复刻和浅复刻浅拷贝&#xff08;Shallow Copy&#xff09;&#xff1a;深拷贝&#xff08;Deep Copy&…

【python】将json内解码失败的中文修改为英文(‘utf-8‘ codec can‘t decode,labelme标注时文件名未中文)

出现问题的场景&#xff1a; 语义分割数据集&#xff0c;使用labelme工具进行标注&#xff0c;然后标注图片存在中文名&#xff0c;导致json标签文件写入中文图片名&#xff0c;从而解析失败。 代码解析json文件时&#xff0c;出现报错&#xff1a; python脚本需求&#x…

Java 7大排序

&#x1f435;本篇文章将对数据结构中7大排序的知识进行讲解 一、插入排序 有一组待排序的数据array&#xff0c;以升序为例&#xff0c;从第二个数据开始&#xff08;用tmp表示&#xff09;依次遍历整组数据&#xff0c;每遍历到一个数据都再从tmp的前一个数据开始&#xff0…

论文解读--High-resolution Automotive Radar Point Cloud Imaging and Processing

高分辨汽车雷达点云成像和处理 摘要 汽车雷达具有体积小、硬件成本低、全天候工作、高分辨率等公认的优点&#xff0c;是高级驾驶辅助系统(ADAS)必不可少的一类重要传感器。然而&#xff0c;低角度分辨率和低成像性能的限制很难满足下一阶段ADAS的需要。新兴的4D成像雷达采用多…

【随笔】Git 高级篇 -- 不带 source 参数的命令 git fetch git push(三十九)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

【工具】如何提取一个mp4文件的关键帧

文章目录 怎么做如何安装ffmepgUbuntu 或 DebianCentOS 或 FedoramacOSWindows其他 Linux 发行版 实践什么是关键帧 怎么做 你可以使用ffmpeg这个强大的多媒体处理工具来提取mp4文件中的关键帧。以下是一个示例命令&#xff0c;可以使用ffmpeg从mp4文件中提取关键帧&#xff1…

一款免费的PDF转换工具分享

最近在吾爱上发现一款PDF免费转换工具&#xff0c;支持多种格式转换&#xff0c;试了一下&#xff0c;还不错 最重要的是免费&#xff0c;不用开会员转换&#xff0c;也没有限制&#xff08;文末有工具地址&#xff09; ps:转换完成后看一下是否符合&#xff0c;可能会有些许…

哇哦,一个超级牛逼的图片格式!!使用它之后我们系统加载图片快了一倍!!! 图片格式转换webp学习!

什么是webp格式&#xff1f; WebP 格式是一种图像文件格式。 它是由谷歌开发的&#xff0c;旨在提供一种高效的图像压缩方式&#xff0c;同时保持较好的图像质量。WebP 格式具有较小的文件体积&#xff0c;能够在一定程度上减少网络传输的数据量&#xff0c;提升网页加载速度…

网工常用工具——Xshell

今天给各位介绍一下&#xff0c;Xshell工具 Xshell是一款功能强大的终端模拟器&#xff0c;主要用于Windows操作系统&#xff0c;用于远程访问和管理服务器&#xff0c;允许用户通过SSH&#xff08;Secure Shell&#xff09;协议安全地连接到远程Linux/Unix服务器或其他支持SS…

DenseCLIP论文讲解

文章目录 简介方法总体框架 &#xff08;Language-Guided Dense Prediction&#xff09;上下文感知提示 &#xff08;Context-Aware Prompting&#xff09;应用实例 论文&#xff1a;DenseCLIP: Language-Guided Dense Prediction with Context-Aware Prompting 代码&#xff1…

Spring与AI结合-spring boot3整合AI组件

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 目录 写在前面 spring ai简介 单独整合al接口 整合Spring AI组件 起步条件 ​编辑 进行必要配置 写在最后 写在前面 本文介绍了springboot开发后端服务中&#xff0c;AI组件(Spring A…

淘宝扭蛋机小程序:开启惊喜购物的新纪元

一、引言 随着科技的飞速发展&#xff0c;我们的购物方式也在不断地更新换代。淘宝&#xff0c;作为国内领先的电商平台&#xff0c;始终致力于为用户提供更加便捷、有趣的购物体验。为了满足广大用户对于新鲜、刺激购物体验的追求&#xff0c;淘宝特别推出了扭蛋机小程序&…

[C++] const 成员函数

标题&#xff1a;[C] this指针 & const 成员函数 水墨不写bug 正文开始&#xff1a; 目录 &#xff08;一&#xff09;Cpp的面向对象编程 &#xff08;二&#xff09;this指针 &#xff08;三&#xff09;const修饰的成员函数 在正式讲解const修饰成员函数之前&#x…

实测ChatGPT插件真香用法!视频一键变脑图,高数作业轻松拿捏

Sam Altman诚不我欺&#xff1a; ChatGPT插件和联网功能终于在这两天向尊贵的Plus用户全面开放了。 像之前预告的一样&#xff0c;联网可以直接获取2021年9月之后的消息&#xff0c;插件也安排了70多个&#xff0c;购物订餐订机票等日常功能应有尽有&#xff0c;更专业的数学、…

网站未部署证书有何影响,如何解决?

如果您的网站没有ssl证书会有以下风险 1 浏览器标记为不安全 未安装证书的网站在访问时会有不安全的提示弹窗或者在网址栏直接显示不安全 2 影响企业信誉 当用户访问网站时看到不安全提示&#xff0c;会对网站的真实性和安全性产生怀疑&#xff0c;不敢轻易与该企业合作&…

Python-VBA函数之旅-setattr函数

目录 一、setattr函数的常见应用场景 二、setattr函数使用注意事项 三、如何用好setattr函数&#xff1f; 1、setattr函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://blog.csdn.net/ygb_1024?…