withastro / astro

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

🐛 BUG: React components using `client:only` do not render children #2265

Closed tylergaw closed 2 years ago

tylergaw commented 2 years ago

What version of astro are you using?

0.21.13

What package manager are you using?

yarn

What operating system are you using?

Mac

Describe the Bug

Related issue #2215

When using client:only hydration of React components, no child components render.

Given:

<Parent client:only>
  <div>I am child</div>
</Parent>

where Parent is

const Parent = (props) => {
  return <div>{props.children}</div>
}

The containing div of Parent will render, but not <div>I am child</div>.

Things I tried

I thought maybe the children also needed client:only, but that didn't change anything.

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-agx2hb-lqeozd?file=src/pages/index.astro

sjerratsch commented 2 years ago

I'm facing the same issue. After looking through the code, it seems to me that this is on purpose somehow..

This is the line where in the html gets rendered if the component is client:only. As you can see, the slot used here is slots.fallback. https://github.com/withastro/astro/blob/affb114ee9ece826f0f02d9c3d1bcbb366fe42d7/packages/astro/src/runtime/server/index.ts#L219

Here it is slots.default, and it renders the html correctly. https://github.com/withastro/astro/blob/affb114ee9ece826f0f02d9c3d1bcbb366fe42d7/packages/astro/src/runtime/server/index.ts#L121

So basically the children of the react component are used as a fallback in case the react component cannot be rendered. I tried to replace .fallback with .default and it worked in the sense that the html of the children got rendered to the static page html. However the children html is then replaced with the react component – which correctly implements a fallback behavior. To avoid the replacement, I had to wrap the html with a astro-fragment tag.

So i would say that the question here is, wether this is the intended behavior?

jonathantneal commented 2 years ago

Great followup, @tylergaw.

So i would say that the question here is, wether this is the intended behavior?

@natemoo-re, would you know what the recommendation is?

csarnataro commented 2 years ago

@jonathantneal Probably for very simple use cases a simple workaround could be to embed your original component with children in a new "wrapper" component (without children, with client:only="react") which in turns embeds the original component with the original children.

Easier to show than explain 😄 https://stackblitz.com/edit/github-agx2hb-p6fivz?file=src%2Fpages%2Findex.astro

I had a similar issue and of course this is just a workaround, not the definitive and best solution.

tony-sull commented 2 years ago

This is fixed in the latest version of Astro 🎉

TheElegantCoding commented 2 months ago

this issue is also present with preact