在使用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吗?
我们不应该得到这些错误。如果这样做,似乎会导致所有页面加载完全崩溃。
答案 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>