Modal.confirm中的okText,cancelText 是默认是英文

1,755 阅读3分钟

Modal.confirm okTextcancelText 默认是中文。

image.png image.png

但是开发中偶然是英文,刷新页面恢复中文。

问题复现

以下复现以及代码分析, antd 是 4.14.1

经过测试发现,在两个组件(ComponentA和ComponentA)均使用 Modal.confirm 创建弹窗情况,如下:

// ComponentA
import React, { useState } from 'react'; 
import { Button, Modal} from 'antd';
const showModal = () => ( Modal.confirm({content:'confirm'  })) 
return ( 
    <>
        <Button type="primary" onClick={showModal}> Modal </Button> 
    </> ); 

按照如下步骤复现

  1. ComponentA 通过 Modal.confirm触发弹窗提示,
  2. 卸载 ComponentA
  3. 触发ComponentB弹窗 okText,cancelText 是英文
  4. 刷新(重新渲染ComponentB),ComponentB 弹窗 okText,cancelText 恢复中文

总的来说,使用 Modal.confirm 的组件在卸载后,此时没有重新渲染的组件使用 Modal.confirm okText,cancelText 默认为英文。

问题原因

根本原因: ConfigProvider locale 属性配置错误或者失效。

这里可以参考:

前置背景

首先,官网对locale 属性的定义如下:

image.png

ConfigProvider 实现中可知locale 状态通过 LocaleReceiver 管理

image.png image.png

LocaleReceiver 实现中,没有设置defaultLocale(即上图的legacyLocale)时,locale 是英文标准 (locale/en_US)

image.png

通常在需求开发中,一个项目只有一个 ConfigProvider来统一 antd 组件配置 ,都会把 locale 属性设置为中文语言包,如下:

import zhCN from 'antd/locale/zh_CN';

<ConfigProvider locale={zhCN}> 
    <Page />
 </ConfigProvider>

也就是在开发中,所有 antd 组件的 ConfigProvider 默认都是同一个。

排除一些在组件内使用ConfigProvider 自定义属性,例如下面外层的 ConfigProvider 仅在 Page1 生效,Page2 获取的配置来自于内层 ConfigProvider


<ConfigProvider locale={zhCN}> 
    <Page1 />
    <ConfigProvider locale={zhCN}> 
        <Page2 /> 
    </ConfigProvider>
 </ConfigProvider>

原因解析

简单了解ConfigProvider 的locale属性后,来看看,Modal.confirm 触发的弹窗 okText 是如何渲染的?

当我们没有设置 oktText 属性时, 系统会从 getConfirmLocale 方法获取 runtimeLocale,并将runtimeLocale 中的 justokText 赋值给 oktText 属性。

image.png

getConfirmLocale 的实现中发现, runtimeLocale 默认是英文语言包,其值会通过 getConfirmLocale 改变。

image.png image.png

什么时候 runtimeLocale 会发生变化呢?

Modal.confirmLocaleProvider (等价于<ConfigProvider locale /> )组件,在组件的componentDidMountcomponentDidUpdate 以及 componentWillUnmount以及 LocaleProvider 创建的时候都会改变相关组件的locale 属性。

image.png

其中,在 componentWillUnmount(组件卸载)时,changeComfirmLocale 方法是没有传入参数,而在其他阶段都会传入 ConfigProvider 中的runtimeLocale 配置。

接下来,看看 changeComfirmLocale 方法的实现, changeComfirmLocale 没有入参时,返回的是默认(英文语言包)的组件配置

image.png

这也就不难发现,为什么卸载组件后,其他组件的 modal 文案变为英文,刷新组件后又恢复中文。

解决方案

方案一: 使用 Modal useModal 创建modal实例替换 Modal.confirm(推荐)

antd 官网也这样解释,Modal.confirm方法是使用 ReactDOM.render 重新渲染一个 React 根节点上,和主应用的 React 节点是脱离的。

image.png

相反, useModal 创建modal实例,通过 hooks 创建 context 从而获取 contextHolder 的上下文环境(包括 locale 属性)。

image.png 如下,Modal.useModal()创建的每个 modal 都是一个实例对象.

const [modal, contextHolder] = Modal.useModal();
React.useEffect(() => {
  modal.confirm({
    content:'confirm' 
  });
}, []);
return <div>{contextHolder}</div>;

方案二: Modal.confirm中配置固定的okText

从前置背景中,我们可以知道Modal.confirmokText在没有配置时,才会根据 locale 匹配语言包获取默认值。

image.png

如下,Modal 一直都会是中文。


 Modal.confirm({
      title: '确定离开当前弹窗吗?',
      okText: '确定',
      cancelText: '取消'
 )}