我想在我的react-redux连接的组件上使用react-i18next,但不确定如何去做。
我已经简化了代码,以显示连接组件的示例:
import React from 'react';
import {connect} from 'react-redux';
import {userSelectors} from "./userSelectors";
interface IConnectedProps {
activeUserName: string | undefined;
}
export class LandingPageComponent extends React.Component<IConnectedProps> {
public render(): JSX.Element {
return (
<React.Suspense fallback={<Spinner/>}>
<React.Fragment>
<div>
... a bunch of controls using translated text
</div>
<div>{activeUserName}</div>
</React.Fragment>
</React.Suspense>
);
}
}
const mapStateToProps = (state: ICoreRootState) : IConnectedProps => ({
activeUserName: userSelectors.getDisplayName(state),
});
export const LandingPage = connect(mapStateToProps)(LandingPageComponent);
已安装的软件包版本:
react version: 16.8.4
react-redux version: 5.1.1
react-i18next version: 10.6.0
我尝试过的事情:
1)当我使用withTranslation,WithTranslation时,出现以下错误:
export class LandingPageComponent extends React.Component<IConnectedProps & WithTranslation> {...}
export const LandingPage = connect(mapStateToProps)(withTranslation()(LandingPageComponent));
错误:
The above error occurred in the <withI18nextTranslation(LandingPageComponent)> component:
in withI18nextTranslation(LandingPageComponent) (created by Connect(withI18nextTranslation(LandingPageComponent)))
in Connect(withI18nextTranslation(LandingPageComponent))
in Route
in t
in Connect(t) (at App.tsx:49)
in Switch (at App.tsx:45)
in App (at src/index.tsx:14)
in Router (created by ConnectedRouter)
in ConnectedRouter (created by Connect(ConnectedRouter))
in Connect(ConnectedRouter) (at src/index.tsx:13)
in Provider (at src/index.tsx:12)
2)当我使用withTranslation,WithTranslation时,出现以下错误:
export class LandingPageComponent extends React.Component<IConnectedProps & WithTranslation> {...}
export const LandingPage = withTranslation()(connect(mapStateToProps)(LandingPageComponent));
错误:
index.js:1446 The above error occurred in the <withI18nextTranslation(Connect(LandingPageComponent))> component:
in withI18nextTranslation(Connect(LandingPageComponent))
in Route
in t
in Connect(t) (at App.tsx:49)
in Switch (at App.tsx:45)
in App (at src/index.tsx:14)
in Router (created by ConnectedRouter)
in ConnectedRouter (created by Connect(ConnectedRouter))
in Connect(ConnectedRouter) (at src/index.tsx:13)
in Provider (at src/index.tsx:12)
3)我不能使用useTranslation,因为不允许在类中使用钩子。
我还尝试了以下方法:
... a bunch of imports
interface ILogoutButtonProps {
userName?: string;
}
interface IConnectedHandlers {
readonly logout: any;
readonly push: any;
}
class InnerLogoutComponent extends React.Component<IButtonProps & IConnectedHandlers & ILogoutButtonProps & WithTranslation, {}> {
public render() {
const {userName, onClick, logout: Logout, push: Push, ...buttonProps} = this.props;
const logoutText = this.props.i18n.t(StringNames.logout);
const buttonText = userName ? logoutText + " " + userName : logoutText;
return (
<Button {...buttonProps} text={buttonText} onClick={this.handleClick}/>
);
}
private handleClick = (event: React.MouseEvent<HTMLElement>) : void => {
this.props.logout()
.then(() => this.props.push(LoginPaths.verifyUser));
}
}
const InnerLogoutTranslatedComponent = withTranslation()(InnerLogoutComponent);
class LogoutComponentInternal extends React.Component<IButtonProps & IConnectedHandlers & ILogoutButtonProps, {}> {
public render () {
return (
<InnerLogoutTranslatedComponent {...this.props}/>
);
}
}
export const LogoutComponent = connect(null,{logout, push})(LogoutComponentInternal);
但出现以下错误:
Hooks can only be called inside the body of a function component.
提前谢谢...
答案 0 :(得分:0)
我实际上很难确定将组件包装在HOC中的顺序。在我目前正在工作的项目中,我们像withNamespaces(connect(withStyles(component)))
一样包装,效果非常好(withNamespaces
与withTranslations
基本相同)。尝试连接翻译后的组件时遇到问题,您现在可能会遇到相同的问题。因此,这是我们的操作方式:
您有一个“正常”组件,例如
type InjectedProps = StateProps & ExternalProps & MyComponentsTranslations
export class MyComponent extends React.Component<InjectedProps> {
...
}
(注意:该过程与功能组件完全相同)
您可以const MyConnectedComponent = connect(mapStateToProps, mapDispatchToProps)(MyComponent)
最后,你做一个
import {WithNamespaces, withNamespaces} from "react-i18next"
export const LocalizedMyComponent = withNamespaces()(
({t,...rest}): WithNamepsaces) => (
<MyConnectedComponent translations={{ put translations here }} {...rest} />
)
)
现在,诀窍是我们定义一个interface MyComponentsTranslations {}
,在其中放置所有必需的翻译或翻译功能(如果是复数形式)。
MyComponentsTranslations
被添加到InjectedProps
,以使其在原始组件中可用。
您总是可以简单地将i18n的t
功能注入到您的组件中,但是在我当前的项目中,我们认为使用它更干净
让我知道这是否适合您。
此外,为了使整个过程更加美观,可以使用以下帮助器:
export interface Translations<T> {
translations: T
}
export const createTranslations = <T>(translations: T): Translations<T> => ({
translations,
})
这允许您设置
type InjectedProps = StateProps & Translations<MyComponentTranslations>
并在withNamespace
中:
<MyConnectedComponent {...createTranslations<MyComponentTranslations>({ put translations here })} {...rest} />
答案 1 :(得分:0)
对于我来说,我是通过以下方式解决的:
export default withTranslation(null, {withRef: true})(MyComponent);
withRef
默认为false
。
来源:https://github.com/i18next/react-i18next/blob/master/src/withTranslation.js
答案 2 :(得分:0)
在我们的项目中,我们成功利用了这一点:
import { compose } from 'redux';
import { withNamespaces } from 'react-i18next';
import { connect } from 'react-redux';
...
export default compose(withNamespaces('translation'), connect(mapStateToProps))(ComponentName);
通过此操作,我们使用 mapStateToProps 连接到 Redux ,并且具有翻译。
答案 3 :(得分:0)
我正在将SSR与RazzleJS一起使用,在我看来,它的工作非常正常。我这样连接connect
和withTranslation
:
export default connect(mapStateToProps,mapDispatchToProps)(withTranslation()(Component));
答案 4 :(得分:0)
这对我有用:
eval()