Search code examples
reactjstypescripti18nextreact-i18next

How to use the t() function in a class component with a constructor?


Using i18next with react, I would like to use the t() function in class components, but most of the time, I also need to initialize the state, so I would like to have a constructor as well.

Following the documentation here I get this:

import React from 'react';
import {WithTranslation, withTranslation} from "react-i18next";

interface ExampleProps extends WithTranslation {

}

interface ExampleState {

}

class Example extends React.Component<ExampleProps, ExampleState> {
    render() {
        const t = this.props.t;
        return (
            <div>
                <p>{t('Test')}</p>
            </div>
        );
    }
}

export default withTranslation()(Example);

This works fine, no problem here. Until I add a constructor:

    constructor(props: ExampleProps, context: any) {
        super(props, context);
    }

withTranslation won't work with this:

TS2345: Argument of type 'typeof Example' is not assignable to parameter of type 'ComponentType<WithTranslationProps>'.   Type 'typeof Example' is not assignable to type 'ComponentClass<WithTranslationProps, any>'.     Types of parameters 'props' and 'props' are incompatible.       Type 'WithTranslationProps' is missing the following properties from type 'WithTranslation<"translation">': t, tReady

enter image description here

If I use interface ExampleProps extends WithTranslationProps {} the type incompatibility disappears, but I can't access the t function, because the WithTranslationProps only has a i18n? nullable type and I can't add anything to the ExampleProps, because I get Property 'newProperty' is missing in type 'WithTranslationProps' but required in type 'ExampleProps'.

const t1 = this.props.i18n?.t; results in TS2722: Cannot invoke an object which is possibly 'undefined' when trying to call t('Test').

const t2 = this.props.t; does not exists.

One solution, If I just initialize the state directly in the class, like:

class Example extends React.Component<ExampleProps, ExampleState> {
    state = {
      // set state here
    }

    render() {

Although I would still like to know if there is a way to use a constructor here.


Solution

  • From the React documentation:

    If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.

    But, wait a minute, what is the context you passed to constructor?

    you only need to pass props as the parameter of the constructor.

    constructor(props)