在带有装饰器和 HOC 的类组件中使用 react-i18next
Posted
技术标签:
【中文标题】在带有装饰器和 HOC 的类组件中使用 react-i18next【英文标题】:Use react-i18next in class components with decorators and HOC 【发布时间】:2019-10-21 11:05:41 【问题描述】:我正在尝试在我的 React 项目中实现 i18n,该项目也在 react-i18next
的帮助下使用 Redux。
在这个项目中,我们使用带有装饰器的类组件。
最初,我想尝试react-i18next
v10,但由于它依赖于钩子并且我不能在类组件中使用它们,所以对我来说这是不可能的。
回到旧版 v9,我按照分步指南 (https://react.i18next.com/legacy-v9/step-by-step-guide) 执行了以下步骤:
创建了带有翻译的i18n.js
配置文件
用i18nextProvider
包裹了我的根容器
ReactDOM.render(
<Provider store=store>
<Router history=history>
<I18nextProvider i18n=i18n>
<RootContainer />
</I18nextProvider>
</Router>
</Provider>,
$root,
);
使用withNamespaces()
HOC 包装了一个简单组件,它是RootContainer
的子组件,但使用了装饰器语法
@withNamespaces()
export default class SimpleComponent extends React.PureComponent
// (... component class code ...)
没有装饰器的情况等同于以下内容:
class SimpleComponent extends React.PureComponent
// (... component class code ...)
export default withNamespaces()(SimpleComponent);
我一定是遗漏了一些东西,因为我在 s-s-r 期间收到以下错误:
react-i18next:: You will need pass in an i18next instance either by props, using I18nextProvider or by using i18nextReactModule. Learn more https://react.i18next.com/components/overview#getting-the-i-18-n-function-into-the-flow
0|s-s-r-dev | TypeError: Cannot read property 'wait' of null
0|s-s-r-dev | at NamespacesConsumerComponent.render (/client/node_modules/react-i18next/dist/commonjs/NamespacesConsumer.js:220:33)
问题是,如果我删除组件类上的@withNamespaces()
HOC,我将不再出现此错误,但是组件的道具中没有t, i18n
,因此无法翻译任何内容。
此外,不幸的是,错误中的给定 URL 不再存在。
正如我从文档中了解到的,<I18nextProvider>
应该将t, i18n
值向下传递到组件树,而我的情况并非如此。
我发现自己陷入了无法使用 v10(我们有很多组件,目前我不能将它们全部重构为功能组件)和无法使 v9 正常工作之间。
我的选择已经不多了,如果你遇到过类似的问题,我可以使用后见之明。
提前致谢。
【问题讨论】:
【参考方案1】:对于任何想知道的人,我通过在渲染器方法中包装 <RootContainer>
子而不是包装 <RootContainer>
本身来使其工作,这给我留下了如下内容:
ReactDOM.render(
<Provider store=store>
<Router history=history>
<RootContainer />
</Router>
</Provider>,
$root,
);
根容器
import i18n from "../core/translations/i18n";
import I18nextProvider from "react-i18next";
@connectWithStore(mapStateToProps, mapActionsToProps)
export default class RootContainer extends React.PureComponent
// (... class code ...)
render
return (
<I18nextProvider i18n=i18n>
<div>
<SimpleComponent/>
</div>
</I18nextProvider>
);
简单元素
import withNamespaces from "react-i18next";
@withNamespaces()
export default class SimpleComponent extends React.PureComponent
// (... class code ...)
componentDidMount()
// Successfully logging the values below
console.warn("Got i18n props?",
t: this.props.t,
i18n: this.props.i18n,
);
唯一的区别是我的渲染器是一个函数,而不是一个组件本身,而RootContainer
是一个成熟的 React 组件(准确地说是 PureComponent)。也许它与渲染链接有关,不确定,但它仍然可以按预期方式工作。
【讨论】:
【参考方案2】:我通过这样做在课堂上使用了最新版本的 react-i18next:
import withTranslation from 'react-i18next';
class RootContainer extends React.Component
constructor(props)
super(props);
render()
<span>this.props.t('Home')</span>
【讨论】:
那么导入 withTranslation 是为了什么?以上是关于在带有装饰器和 HOC 的类组件中使用 react-i18next的主要内容,如果未能解决你的问题,请参考以下文章