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

时间:2019-08-20 07:24:42

标签: reactjs intl

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

错误消息

Invariant Violation: [React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.

我们的应用程序很小。我们有三页,其中一页嵌入了多个模式对话框,然后用户可能会打开它们。我们无法确定该问题的确切浏览器,版本或代码指向。

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

我们的main.js渲染器被IntlProvider包装:

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

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

父组件已注入Intl:

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

export default injectIntl(Page);

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

我们不应该得到这些错误。如果这样做,似乎会导致所有页面加载完全崩溃。

2 个答案:

答案 0 :(得分:0)

为我解决此问题的解决方案是确保每次需要在jest测试中装入组件时,都使用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);
});

您需要确保每个笑话测试都遵循此安装公式。您应该在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 },
  });
}

答案 1 :(得分:0)

对我来说,我的 ErrorBoundaries 超出了 IntlProvider 的范围

    <Router>
        <SentryBoundary>
         <IntlProvider locale={this.state.lang} messages={localeData[this.state.lang]}>
            <Navbar lang={this.state.lang} changeLang={this.changeLang} />
            <div>
                <Route exact path="/" render={(props) => <Start{...props} />}/>
            </div>
         </IntlProvider>
        </SentryBoundary>
    </Router>

我所要做的就是将边界移动到 IntlProvider 的内部

    <Router>
      <IntlProvider locale={this.state.lang} messages={localeData[this.state.lang]}>
        <SentryBoundary>
            <Navbar lang={this.state.lang} changeLang={this.changeLang} />
            <div>
                <Route exact path="/" render={(props) => <Start{...props} />}/>
            </div>
        </SentryBoundary>
      </IntlProvider>
    </Router>