Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This JSX tag's 'children' prop expects a single child of type 'ReactI18NextChild | Iterable<ReactI18NextChild>' when using allowObjectInHTMLChildren #1543

Closed
davehowson opened this issue Aug 15, 2022 · 86 comments · Fixed by #1606 or i18next/next-i18next#2087
Assignees

Comments

@davehowson
Copy link

davehowson commented Aug 15, 2022

🐛 Bug Report

After upgrading to React v18 and Reacti18Next to v11.18, I had an issue with objects not being accepted inside the Trans component, something similar to this.
The fix for that was to add the allowObjectInHTMLChildren property, which fix that issue, but it lead to another issue.
Now, when I try to have the result of a t function along with some other strings inside a p or span component, I get the error

This JSX tag's 'children' prop expects a single child of type 'ReactI18NextChild | Iterable<ReactI18NextChild>' when using `allowObjectInHTMLChildren

To Reproduce

Codesandbox - https://codesandbox.io/s/react-i18next-type-issue-uidhq7
Please check the error on src/App.tsx:10

<p>{t("simpleContent")} with extra stuff</p>

Proposed Solution

I tried playing around with the types in the library and it seems like changing node_modules/react-i18next/ts4.1/index.d.ts:108 as follows will fix this.

declare module 'react' {
  interface HTMLAttributes<T> {
    children?: ReactI18NextChild | ReactI18NextChild[];
  }
}

The problem, at least for me, seems to be with Iterable<ReactI18NextChild> not working as expected for multiple children

@ghost
Copy link

ghost commented Aug 23, 2022

Hi @pedrodurek, any update on this?
I was planning on using https://github.com/ds300/patch-package to solve this for now, unless a PR is in the works?

@eiskalteschatten
Copy link

We're also having this problem unfortunately. ☹️

@debugelton
Copy link

same problem also with React 17 and react-i18next (v11.18.3)

@JCMais
Copy link

JCMais commented Sep 14, 2022

This is probably because the type definition is React.ReactNode | Record<string, unknown>, while i18next type definition has object in the union type: https://github.com/i18next/i18next/blob/132a02461479c1b14709ff0bce1db484578ccb30/index.d.ts#L687

I think (could be wrong) that Record<string, unknown> and object are not compatible if you change i18next to React.ReactNode | object it works.

I also changed from Iterable<ReactI18NextChild> to ReactI18NextChild[]

@neatroapp
Copy link

I'm having a similar problem with PropTypes.InferProps. If I use PropTypes.node for my children prop, and use {children} in a simple div, I get this error:

Type 'ReactNodeLike' is not assignable to type 'ReactI18NextChild | Iterable'.
Type '{}' is not assignable to type 'ReactI18NextChild | Iterable'.

@sshmyg
Copy link

sshmyg commented Sep 20, 2022

Never do this in open source libs.
If you want to get custom children, use custom (alias) types. Never reassign types of different lib!

image

@kanonieer
Copy link

Same problem after bumping React to v18

@rjaguilar
Copy link

Same

@davidpp
Copy link

davidpp commented Sep 26, 2022

Same issue here

@estrelasteinkirch
Copy link

same here

@cuttleman
Copy link

same issue here

@rene-stesl
Copy link

rene-stesl commented Oct 12, 2022

same issue if you have something like <span>{props.somePassedInReactNodeOrReactElement}</span>

Type 'ReactNode' is not assignable to type ReactI18NextChild | Iterable<ReactI18NextChild>.

@stale
Copy link

stale bot commented Oct 20, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 20, 2022
@renomateo
Copy link

Same issue here

@stale
Copy link

stale bot commented Oct 29, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 29, 2022
@sklawren
Copy link

Same issue

@stale stale bot removed the stale label Oct 31, 2022
@sergiohgz
Copy link

This is a big issue relative to typingm due to redefining children of react module.
This is not a good practise, as it breaks other typings.

This JSX tag's 'children' prop expects a single child of type 'ReactI18NextChild | Iterable<ReactI18NextChild>', but multiple children were provided.
but multiple children were provided.

@rene-stesl
Copy link

Is that really the solution to just ignore the growing number of Typescript Users?
Why has this type been overridden in the first place? Just leave react typings alone, please!
Does it really need that override? What is it for?

@jamuhl
Copy link
Member

jamuhl commented Nov 10, 2022

@rene-stesl idk...but this module is far from ignoring typescript users. Just go through the changelog https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md and check how many releases are just related to work for typescript users.

@pedrodurek puts a lot of his own (free) time into improving the typings and does an awesome job for the community.

@pedrodurek
Copy link
Member

Thanks for backing me up @jamuhl, I appreciate it!

@rene-stesl, the types here work perfectly, sometimes it's just hard to please everyone, but I'm doing my best here to address the issues whenever I have free time.
When it comes to complex types like the i18next ones, where we recursively go through all translations to infer the appropriate keys and return type, we need to be careful to address some issues due to compilation time concern, so there is a lot of effort on testing and benchmarking it.

@rene-stesl
Copy link

@jamuhl, @pedrodurek I know that it is not easy to sacrifice your free time for such a project and only get criticism. This is definitely not my intention.

But IMHO this ticket gets ignored since it was opened on Aug 15. I personally don't think the Types work perfectly in this case because if you just add react-i18next as dependency to an existing project it is possible that the build fails! And I personally think that just adding a dependency to a project shouldn't be able to do that!

If someone can explain why the React Types were overwritten, it might be easier to find a solution.

@jamuhl
Copy link
Member

jamuhl commented Nov 11, 2022

@rene-stesl

I guess (not a typescript user):

  • react team decided to make types stricter not allowing objects inside the react-element children array (as it makes no sense to their use case -> you can't render objects)

in react-i18next we decided long before that objects are a good way to pass in interpolation values and keeping i18next translation syntax <Trans>Some interpolation by passing in an object {{theObject}}</Trans>. That is absolute valid in javascript.

So the solution is either to extend the types or not using objects inside react-elements.

(Like said - i don't use typescript - so I just believe that this was the reason)

@serjiosilent
Copy link

@adrai in my case I'm not using any translations in components, just installed react-i18next and after running app get this error

@adrai
Copy link
Member

adrai commented Sep 8, 2023

@adrai in my case I'm not using any translations in components, just installed react-i18next and after running app get this error

I can't see any error in the codesandbox example.

@sourdenis
Copy link

sourdenis commented Sep 8, 2023

@adrai according to this: https://www.i18next.com/overview/getting-started, my config seems legit :) "translation" <-- this is default ns ;)

I changed the i18n confing so that it includes ns "default" and even added to useTranslation() hook, that it would use the "default" ns.

The error is the same :)

@adrai
Copy link
Member

adrai commented Sep 8, 2023

@adrai according to this: https://www.i18next.com/overview/getting-started, my config seems legit :) "translation" <-- this is default ns ;)

also in the getting started guide you see the translation namespace is defined in the language object:
image

but your example has no namespace:
image

@sourdenis
Copy link

sourdenis commented Sep 8, 2023

Screenshot 2023-09-08 at 11 50 14

I see this error

here is the fork version :) : https://codesandbox.io/s/i18next-type-error-mui-forked-ht2ctc

@adrai
Copy link
Member

adrai commented Sep 8, 2023

Screenshot 2023-09-08 at 11 50 14 I see this error

This is not an i18next problem...
You might ask @mui/material because the TextField is not from react-i18next

@sourdenis
Copy link

@adrai according to this: https://www.i18next.com/overview/getting-started, my config seems legit :) "translation" <-- this is default ns ;)

also in the getting started guide you see the translation namespace is defined in the language object: image

but your example has no namespace: image

ok, that was my bad. Sry.
But it doesn't change the outcome

@sourdenis
Copy link

well, it works with older version of i18next / react-i18next :)

@adrai
Copy link
Member

adrai commented Sep 8, 2023

@nicegamer7 can you have a look at this?
maybe this can be optimized? #1669
16312ff

@nicegamer7
Copy link
Contributor

This looks like an issue with MUI's types. I'll take a look when I get a chance.

@nicegamer7
Copy link
Contributor

I found the issue in MUI's types. I'll make a PR there in a bit and post here when I do.

@nicegamer7
Copy link
Contributor

You can install the version of mui-material from the above PR by setting the version to https://pkg.csb.dev/mui/material-ui/commit/69a9e797/@mui/material in your package.json. If anyone who was experiencing the issue could try it and report whether this fixes it, that'd be appreciated.

@nphmuller
Copy link

nphmuller commented Sep 8, 2023

The error is gone with the version you linked. Haven't been able to test everything thoroughly because there are a few other breaking changes in the version that's currently on @mui/material's master branch.

Would it be too much to ask you to explain the fix? I see you typed the children prop of <FormControl /> as React.HTMLAttributes<HTMLDivElement>['children'] and the children prop from <FormLabel /> from React.LabelHTMLAttributes<HTMLLabelElement>['children'] instead of React.ReactNode. Is this component special, or would you expect other libraries to potentially do the same? If I understood correctly the "normal" typing of the children prop should be React.ReactNode, so I don't yet understand why this rule doesn't apply for these components.

@nicegamer7
Copy link
Contributor

The argument in the renderInput prop is typed as containing React.HTMLAttributes<HTMLDivElement>['children'] and React.HTMLAttributes<HTMLLabelElement>['children'], so if these types are augmented (as they are in this package), you'll get a type error if you try to pass these to a component expecting React.ReactNode.

Does that make sense? Hopefully my explanation is okay.

@nphmuller
Copy link

Ah, so there was a mismatch in their own typings. That totally makes sense. Thanks for explaining!

@developergunny
Copy link

developergunny commented Sep 14, 2023

I also had the same problem as @serjiosilent

Following @sourdenis advice, I downgraded to react-i18next v.12.2.2 and i18next v.22.5.1 and the problem went away.

@MrTim
Copy link

MrTim commented Oct 5, 2023

For those who will bump into the same issue, I'll share my experience regarding this problem.

I got same error with following dependencied (listing only important ones):

"devDependencies": {
  "react-scripts": "^5.0.0",
  “typescript”: “^4.6.2"
},
"dependencies": {
  "i18next": "^23.5.1",
  "react": "^18.2.0",
  "react-dom": "^18.2.0",
  "react-i18next": "^13.2.2"
}

Important here is a version of typescript.
After I updated to typescript v5 the error is gone. You would get another problem of legacy peer deps (because cra doesn't support latest typescript version) and that will be a trade of in using latest versions of i18next libs.

@csharpsi
Copy link

You can install the version of mui-material from the above PR by setting the version to https://pkg.csb.dev/mui/material-ui/commit/69a9e797/@mui/material in your package.json. If anyone who was experiencing the issue could try it and report whether this fixes it, that'd be appreciated.

@nicegamer7 this resolved the issue for me, thanks! Hopefully your PR gets merged soon 🤞

@irangarcia
Copy link

It will get fixed?

#1543 (comment)

@bretuobay
Copy link

I just run into this. The fix was to wrap the props with React.PropsWithChildren

@vu-cv
Copy link

vu-cv commented Oct 29, 2023

Screenshot 2023-09-08 at 11 50 14 I see this error

This is not an i18next problem... You might ask @mui/material because the TextField is not from react-i18next

@sourdenis Hi my friend, how to fix it

@FOSSforlife
Copy link

In my case, using MUI Autocomplete with MUI TextField, here was the solution:

Replace:

      renderInput={(params) => (
        <TextField {...params} />
      )}

with:

      renderInput={(params) => (
        <TextField {...(params as AutocompleteRenderInputParams & { InputLabelProps: React.PropsWithChildren<InputLabelProps> })} />
      )}

@vitaliihra
Copy link

I experiencing a similar to serjiosilent and sourdenis issue
So, I used the older react-i18next(11.18.0) version it worked, but can anyone explain why it happened?

Why did only the installation of react-i18next cause these issues with MUI's TextFields?

Thanks in advance.

@zhouru1bin
Copy link

Have the same issue with using MUI.

Importing TextField and get an error:

Type '{ label: string | undefined; placeholder: string | undefined; variant: "filled"; fullWidth: true; id: string; disabled: boolean; size: "small" | undefined; InputLabelProps: Omit<HTMLAttributes<HTMLLabelElement>, "color">; InputProps: { ...; }; inputProps: InputHTMLAttributes<...>; }' is not assignable to type 'Omit<OutlinedTextFieldProps | FilledTextFieldProps | StandardTextFieldProps, "variant">'.
  The types of 'InputLabelProps.children' are incompatible between these types.
    Type 'ReactI18NextChildren | Iterable<ReactI18NextChildren>' is not assignable to type 'ReactNode'.
      Type 'Record<string, unknown>' is not assignable to type 'ReactNode'.
        Type 'Record<string, unknown>' is missing the following properties from type 'ReactPortal': key, children, type, props

Any solution didn't helped

UPD: application become to stable after I set "react-i18next": "^11.18.0"

I also encountered the same problem, have you solved it?

@vitaliihra
Copy link

@zhouru1bin you can either downgrade the react-i18next or use the pr of mui above. Also, when I updated the typescript to v5 it solved the issue for me, but I am not sure why it appeared after all

@herzaso
Copy link

herzaso commented Jan 1, 2024

any reason not to use the following syntax?

<Trans i18nKey='MY_KEY' values={{foo: 'bar'}}>
  Hello <b>{foo}</b>
</Trans>

Assuming MY_KEY = Hello <1>{{foo}}</1>

(instead of passing object as a child, just pass the value)

@undefinederror
Copy link

any reason not to use the following syntax?

<Trans i18nKey='MY_KEY' values={{foo: 'bar'}}>
  Hello <b>{foo}</b>
</Trans>

Assuming MY_KEY = Hello <1>{{foo}}</1>

(instead of passing object as a child, just pass the value)

That would not work with i18next-parser, which would write MY_KEY = "Hello <1>{foo}</1>" in your translation file.

What seems to work for me is

<Trans i18nKey='MY_KEY' values={{foo: 'bar'}}>
  Hello <b>{'{'}{foo}{'}'}</b>
</Trans>

Which does correctly write MY_KEY = "Hello <1>{{foo}}</1>" in your translation file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet