antd3升级antd5升级踩坑-message组件

前言

最近在从antd3升级到antd5到时候,遇到一个问题,有客户报过来在部分低版本360浏览器会出现antd到message全局提示无法自动关闭的问题,这里记录一下解决的过程

解决过程

首先我们想到的是不是兼容问题导致的,antd5有使用:where选择器来降低选择器的优先级,但是:where在低版本浏览器的兼容性较差,antd官方建议可以使用 @ant-design/cssinjs 取消默认的降权操作

jsx 复制代码
import { StyleProvider } from '@ant-design/cssinjs';

// `hashPriority` 默认为 `low`,配置为 `high` 后,

// 会移除 `:where` 选择器封装

export default () => (

  <StyleProvider hashPriority="high">

    <MyApp />

  </StyleProvider>

);

切换后,样式将从 :where 切换为类选择器:

jsx 复制代码
--  :where(.css-bAMboO).ant-btn {

++  .css-bAMboO.ant-btn {

      color: #fff;

    }

可是这个配置一开始改造的时候我们已经加了,为什么还是不行呢,难道不是这个问题导致的?

然后我们又看了message的文档,发现现在已经不推荐用静态方法的方式来调用,推荐是通过hook的,我们试了一下,通过hook的方式,在360浏览器就正常了。

但是原来的调用在class,hook,service层都有调用,不可能全部改成hook,因为客户叫的也比较凶,我们想到了一个临时方案来解决

首先我们定义了一个MessageHolder组件,这个组件在最顶层引入,组件里面通过eventEmitter监听

消息,收到消息会通过meaageApi调用message组件

MessageHolder.jsx

jsx 复制代码
import React, { useEffect } from'react';

import { message } from'antd';

import ee from"./eventEmitter";


functionMessageHolder(){

const [messageApi, contextHolder] = message.useMessage();


    useEffect(() => {

const messageTypes = ['warning','success','error','info'];

        messageTypes.forEach((m) => {

            ee.on(m, (data) => {

                messageApi[m](data.content);

            });

        })

    }, []);


return <>

    {contextHolder}

     </>;

}

  


exportdefault MessageHolder;

  

eventEmitter.js

jsx 复制代码
import EventEmitter from "events";

if(!window.ee) {

    window.ee =new EventEmitter();

}

exportdefault window.ee;

最后我们实现了一个message.js来兼容原来的message api,这样我们只要改一下引用,调用的地方就不用改了

message.js

jsx 复制代码
import ee from"./eventEmitter";

  


exportdefault {

    warning: (content) => {

        ee.emit('warning', { content });

    },

    error: (content) => {

        ee.emit('error', { content });

    },

    success: (content) => {

        ee.emit('success', { content });

    },

    info: (content) => {

        ee.emit('info', { content });

    }

}

  

这个方式暂时解决了低版本360浏览器的问题,但是问题的原因还是没有找到。

接下来我就开始一步一步调试antd的源码,发现静态方法方式调用message的api其实antd内部是通过render单独渲染的,所以是拿不到我项目里面定义的context的, 这个配置也就没有传下去

那针对这种静态方法调用我怎么把context传下去呢?最后我在github的issue里面找到了答案。antd 5.13.0 以上版本提供了一个配置,这个配置只对静态方法调用生效,通过传递hoderRender可以指定渲染的context

OK通过下面的方式就可以把StyleProvider传下去了,360浏览器里面表现也正常了。

jsx 复制代码
  ConfigProvider.config({

      holderRender: (children) => {

        return <StyleProvider hashPriority="high">

          <ConfigProvider>

              {children}

          </ConfigProvider>

        </StyleProvider>

      },

    });
相关推荐
逆旅行天涯27 分钟前
【Threejs】从零开始(六)--GUI调试开发3D效果
前端·javascript·3d
长风清留扬1 小时前
小程序毕业设计-音乐播放器+源码(可播放)下载即用
javascript·小程序·毕业设计·课程设计·毕设·音乐播放器
m0_748247801 小时前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
ZJ_.2 小时前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
joan_852 小时前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
还是大剑师兰特3 小时前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
Watermelo6173 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
一个处女座的程序猿O(∩_∩)O5 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
燃先生._.11 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js