react-intl v4升级`IntlProvider`未找到阻止组件在使用`injectIntl`包装器时显示
Posted
技术标签:
【中文标题】react-intl v4升级`IntlProvider`未找到阻止组件在使用`injectIntl`包装器时显示【英文标题】:react-intl v4 upgrade `IntlProvider` not found preventing component from displaying when using `injectIntl` wrapper 【发布时间】:2020-08-24 02:37:16 【问题描述】:我正在尝试从 react-intl v 2.3.0 升级到 4.5.1。自升级以来,我在injectIntl
HOC 周围遇到了一些问题。我在 monorepo 中有一个共享组件库,它被导入到不同的功能中(在 repo 的单独部分中组合了导入的共享组件和本地唯一组件)。但是,我的 IntlProvider
存在于我的共享组件库中,我们导入了一个名为 AppShell
的组件,其中包含任何需要的提供程序(包括 intl),这些提供程序封装了每个功能的顶层。
我遵循了关于 formatjs repo 上的问题的建议,并从我的共享组件库中删除了 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
帮助程序,组件会呈现但仍显示错误消息:
injectIntlHelper 代码:
// 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 及更高版本中仍然存在
我已经尝试了不同的组合并在网上查找了几天,是否可以进行任何其他更改来消除这些错误?在版本之间添加或更新时,我缺少什么东西会跳出来吗?
【问题讨论】:
【参考方案1】:对于遇到此问题的任何人,我的问题已通过关注/修改问题中的修复程序得到解决: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;
问题的相关引用:
我认为 [具有多个依赖项] 使用旧版本的原因是旧的 React 上下文 API。新的 React 上下文 API 依赖于相同的引用。您的项目从不同的 node_modules 实例化反应上下文,因此上下文不是相同的引用。这也意味着您在应用程序中捆绑了两次 react-intl。
【讨论】:
以上是关于react-intl v4升级`IntlProvider`未找到阻止组件在使用`injectIntl`包装器时显示的主要内容,如果未能解决你的问题,请参考以下文章