withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
46.65k stars 2.48k forks source link

String passed as child to React component is not of type string when called inside Astro context #10531

Closed andrejilderda closed 7 months ago

andrejilderda commented 7 months ago

Astro Info

Astro                    v4.5.8
Node                     v18.18.0
System                   Linux (x64)
Package Manager          npm
Output                   static
Adapter                  none
Integrations             @astrojs/react

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

I found that when I use a React component inside Astro and pass a string as a child to it the type of the child is string, but a React element (?) in stead. This makes it inconsistent with React, where it is astring.

A use case could be where a user wants to use a React Heading component defined in a design system in both Astro and React contexts. Due to this behavior you can't use string manipulation methods on the children.

What's the expected result?

In the reproduction below I use the Heading inside Astro and once inside a React component (without client:load). I expected the children prop of both to be of type string (see console for the differences).

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-w6f7cc?file=astro.config.mjs,package.json,src%2Fpages%2FHeading.tsx,src%2Fpages%2FHeadingConsumer.tsx,src%2Fpages%2Findex.astro

Participation

florian-lefebvre commented 7 months ago

I had a quick look. When adding client:load, it's expected that it's not a string because it's wrapped with an <astro-slot> to make the island works. But I agree it's weird in this case since it's just a string in the dom, nothing is wrapped. I won't triage this as I'm not familiar enough with the react integration internals but at least here are thoughts for another maintainer

matthewp commented 7 months ago

This is a limitation for how Astro works. Astro is not React, so when we pass something to react it is turned into a special component called "StaticHtml", so that is a vnode that can be passed around as such. The downside is your use-case isn't going to work. If you want a string to manipulate, pass as a prop instead. https://github.com/withastro/astro/blob/main/packages/integrations/react/static-html.js