简体   繁体   中英

Can't use props when passing { t } (from i18n-react) to stateless component

I have the parent component that has the state:

class RecordEdit extends PureComponent {
    state = { 
        allRecordData: {},
        changelog: [
            {hello1: '1'},
            {hello2: '2'}
        ]
    }

It tries to render its child and pass the prop to it:

<div className='cards-container'>
    <ChangeHistory recordEditHistory={this.state.changelog} />
</div>

And the ChangeHistory component tries to map over the received prop to render a list of elements:

const ChangeHistoryCard = ({ t }, props) => (
  <CardOuterContainer recordEditHistory={props.recordEditHistory}>
    <h1>{t('История изменений')}</h1>
    {
      props.recordEditHistory &&
      props.recordEditHistory.map(item =>
        <p>{t('Последнее изменение')}: <span>[22.11.2018]</span></p>
      )
    }
  </CardOuterContainer>
);
export default withNamespaces()(ChangeHistoryCard);

For some reason, the component always thinks that the recordEditHistory prop is undefined. But if a click on it in the inspector, I can see that the value has been passed successfully:

ChangeHistoryCard的道具

I don't understand the problem. Can it be because I use i18n and using withNamespaces does something with props or...? I have to idea how to approach this problem.

IMPORTANT: { t } is from i18n-react, I use it to translate the interface to English and back. I tried removing it completely and it didn't help.

EDIT : I tried removing the { t } method and removing withNamesSpaces() HOC from the export and it all works now. But now i can't use i18n-react in this component :(

I think the problem is with the component params:

const ChangeHistoryCard = ({ t }, props) => ();

Should be:

const ChangeHistoryCard = (props) => ();

the signature of functional component only get props

https://reactjs.org/docs/components-and-props.html

Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.

change

const ChangeHistoryCard = ({ t }, props) => ();

to

const ChangeHistoryCard = (props) => ();

So, if you read the second edit, you would know that if I remove i18n from the component completely, it all seems to work.

That's great, but I really wanted the i18n to stay, so I found a better way:

Instead of passing { t } to the component, you can import 'i18next' and call t as a method of that.

So this:

import { withNamespaces } from 'react-i18next';

const ChangeHistoryCard = ({ t }, props) => (
  <CardOuterContainer recordEditHistory={props.recordEditHistory}>
    <h1>{t('История изменений')}</h1>
    {
      props.recordEditHistory &&
      props.recordEditHistory.map(item =>
        <p>{t('Последнее изменение')}: <span>[22.11.2018]</span></p>
      )
    }
  </CardOuterContainer>
);
export default withNamespaces()(ChangeHistoryCard);

Becomes this:

import { withNamespaces } from 'react-i18next';
import i18next from 'i18next';

const ChangeHistoryCard = (props) => (
  <CardOuterContainer recordEditHistory={props.recordEditHistory}>
    <h1>{i18next.t('История изменений')}</h1>
    {
      props.recordEditHistory &&
      props.recordEditHistory.map(item =>
        <p>{i18next.t('Последнее изменение')}: <span>[22.11.2018]</span></p>
      )
    }
  </CardOuterContainer>
);


export default withNamespaces()(ChangeHistoryCard);

Thay way i18n stays in place, while props remain untouched and usable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM