react-intl 未找到 v4 升级 `IntlProvider` 阻止组件在使用 `injectIntl​​` 包装器时显示

react-intl v4 upgrade `IntlProvider` not found preventing component from displaying when using `injectIntl` wrapper

我正在尝试从 react-intl v 2.3.0 升级到 4.5.1。自升级以来,我 运行 遇到了一些围绕 injectIntl HOC 的问题。我在 monorepo 中有一个共享组件库,它被导入到不同的功能中(在 repo 的单独部分中导入的共享和本地唯一组件的组合)。但是,我的 IntlProvider 存在于我的共享组件库中,我们导入了一个名为 AppShell 的组件,其中包含任何需要的提供程序(包括 intl),它包装了每个功能的顶层。

我听从了关于 formatjs 存储库问题的建议,并从我的共享组件库中删除了 react-intl 版本。这解决了我的大部分问题,但有一些注意事项。

请注意,以下所有示例都使用 react-intl 版本 4.5.1 的功能文件夹,以及未安装 react-intl 版本的共享组件库

修复尝试 1

如果我尝试使用 react-intl 中的 injectIntl HOC,该组件将不会在页面上呈现,并且出现以下错误:

代码示例(AppShell 包装器组件位于顶层 ReactDOM.render 函数中):

import { FormattedMessage, injectIntl } from 'react-intl';

// shared component library
import { Alert } from '@shared/components/alert';
// component custom to feature, also can contain shared components
import WorkspaceListContainer from './workspaceListContainer';
import messages from './messages';

export class AppLifecycleMenu extends Component {
  render() {
    const deleteAlertTitle = this.props.intl.formatMessage(
      messages.deleteAlertTitle,
      { alertName: name }
    );

    return (
        <Fragment>
            <WorkspaceListContainer />
            <Alert
                title={deleteAlertTitle}
                okButtonText={<FormattedMessage {...messages.deleteOkButton} />}
                cancelButtonText={<FormattedMessage {...messages.deleteCancelButton} />}
            />
      </Fragment>
    );
  }
}

export default injectIntl(AppLifecycleMenu);

请注意,在我们的许多共享组件中,intl 消息可以作为 props 传递,并且一些组件包装在它们自己的 injectIntl HOC 到 props 的国际默认版本(例如默认按钮标签)。

修复尝试 2

但是,如果我导入共享资源库中的 injectIntl 帮助程序,组件会呈现但仍会显示错误消息:

injectIntl​​Helper 代码:

// only apply intl in non-test environments
export  default  Component  => process.env.NODE_ENV  ===  TEST_ENV  ?  Component  :  injectIntl(Component);

代码示例(AppShell 包装器组件位于顶层 ReactDOM.render 函数中):

import { FormattedMessage, injectIntl } from 'react-intl';

// shared component library
import { Alert } from '@shared/components/alert';
import injectIntl from '@shared/utilities/injectIntl';
// component custom to feature, also can contain shared components
import WorkspaceListContainer from './workspaceListContainer';
import messages from './messages';

export class DeleteWorkspaceAlert extends Component {
  render() {
    const deleteAlertTitle = this.props.intl.formatMessage(
      messages.deleteAlertTitle,
      { alertName: name }
    );

    return (
        <Fragment>
            <WorkspaceListContainer />
            <Alert
                title={deleteAlertTitle}
                okButtonText={<FormattedMessage {...messages.deleteOkButton} />}
                cancelButtonText={<FormattedMessage {...messages.deleteCancelButton} />}
            />
      </Fragment>
    );
  }
}

export default injectIntl(AppLifecycleMenu);

具有 intlprovider 的组件树:

错误信息:

修复尝试 3

我也试过只在共享资源库中安装 react-intl 但这导致了这个错误消息:

环境

我曾尝试降低 react-intl 中的版本,但这个问题一直存在到 3.0 及更高版本中

我已经尝试了不同的组合并在网上查找了几天,我可以做任何其他更改来消除这些错误吗?有没有什么是我遗漏了在版本之间添加或更新的东西?

对于遇到此问题的任何人,我的问题已通过 following/modifying 问题的修复解决:https://github.com/formatjs/formatjs/issues/1620

与上面链接的问题不同,我的项目 IntlProvider 存在于共享资源库中并被导出以包装组件。因此,我从共享资源库以外的所有文件夹中删除了 react-intl 依赖项,并从那里导出了任何需要的组件。

所以我在非共享组件文件夹中的导入看起来像

import injectIntl, { FormattedMessage, FormattedDate } from '@shared/utils/intl';

我的共享库中的组件具有如下所示的文件

import { FormattedMessage } from 'react-intl;
export FormattedMessage;

本期相关引述:

I think the reason [having multiple dependencies] worked with older version is old React context API. New React context API rely on same reference. You project instantiates react context from different node_modules thus contexts are not same reference. This also means you are bundling react-intl twice in your application.