React Intl - 找不到所需的 `intl` 对象。<IntlProvider> 需要存在于组件祖先中

Rcl*_*cls 15 intl reactjs

在使用 React Intl 进行本地化时,我们不断通过 Airbreak 从我们的 React 应用程序中获取随机错误消息。

错误信息

Invariant Violation: [React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.
Run Code Online (Sandbox Code Playgroud)

我们的应用程序非常小。我们有三页,其中一页嵌入了多个模态对话框,然后可能由用户打开。我们一直无法将这个问题定位到确切的浏览器、版本或代码点。

我们试图深入研究错误消息,并在没有运气的情况下找到确切原因。模态对话框作为主组件的子组件存在,并在呈现父组件时嵌入。

我们的 main.js 渲染是这样用 IntlProvider 包装的:

render() {
    return (
        <ErrorBoundary>
            <IntlProvider locale={language} messages={messages[language]}>
                <Router> 
                    <Route render={({location}) => (
                        <div id="site-container">
                                     ...
Run Code Online (Sandbox Code Playgroud)

ErrorBoundary 是 Airbrake。IntlProvider 获取语言环境和翻译后的字符串。

父组件已注入 Intl:

Page.propTypes = {
intl: intlShape.isRequired
};

export default injectIntl(Page);
Run Code Online (Sandbox Code Playgroud)

IntlProvider 的用法与文档描述的一样,应该使用它,但是我们在这里遗漏了什么吗?这个错误的原因是什么?某些对话框没有获得为它提供的 intl?

我们不应该收到这些错误。如果确实如此,它似乎会导致任何页面加载完全崩溃。

Zac*_*igo 0

对我来说解决这个问题的解决方案是确保每次需要在玩笑测试中挂载组件时都使用 i18n 挂载测试文件。这是一个例子:

it('set the value to 4 if changed value is not a number', () => {
  const wrapper = mountWithTestFileI18N(<Component {...props} />);
  wrapper.find('.form-input').simulate('change', { target: { value: 'tt' } });
  wrapper.find('.form-input').simulate('blur');

  expect(wrapper.find('.form-input').props().value).toBe(4);
});
Run Code Online (Sandbox Code Playgroud)

您需要确保每次玩笑测试都遵循此安装公式。您的 jestsetup.js 文件中应该有安装函数。这是一个例子:

function mountWithIntl(node, intlKeys, formatKeys, { context, childContextTypes } = 
    {}) {
  const { intl } = getIntlContext(intlKeys, formatKeys);
  return mount(nodeWithIntlProp(node, intl), {
    context: { ...context, intl },
    childContextTypes: { ...childContextTypes, intl: intlShape },
  });
}
Run Code Online (Sandbox Code Playgroud)