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

Islands component that accepts children #47

Closed
berlysia opened this issue Feb 13, 2024 · 6 comments · Fixed by #65
Closed

Islands component that accepts children #47

berlysia opened this issue Feb 13, 2024 · 6 comments · Fixed by #65
Labels
enhancement New feature or request

Comments

@berlysia
Copy link
Contributor

berlysia commented Feb 13, 2024

What is the feature you are proposing?

Current islands component can not render children in the client side.

If we were achieve this, it means we have "Donut Components" pattern.

One of the reasons is that the child is not passed in this part, but in addition to this, it seems necessary to modify the hydrate process when an island exists within an island.

@berlysia berlysia added the enhancement New feature or request label Feb 13, 2024
@yusukebe
Copy link
Member

Hi @berlysia

This issue is resolved by #35. I'll release the new version, including the change, later.

@usualoma
Copy link
Member

Hi @berlysia Thanks for the report!
cc @yusukebe

#35 will partially fix this problem, but it does not work correctly when children is a function component. I have an idea to deal with this, so please give me a few days.

@usualoma
Copy link
Member

Support children with server-side Suspense (streaming) is coming soon.

  • Hydrate without waiting for the server side Suspense to resolve, and user can click button.
  • Children are updated according to the server-side Suspense resolve.
ServerClientComponents.mp4
const ChildContent3 = async () => {
  await new Promise((resolve) => setTimeout(resolve, 1000))
  throw new Error('Error in child content 3')
}

const ChildContent2 = async () => {
  await new Promise((resolve) => setTimeout(resolve, 1000))
  return (
    <>
      <p>Counter children 2</p>
      <ErrorBoundary fallback={<p>Something went wrong</p>}>
        <Suspense fallback="<p>Loading...</p>">
          <ChildContent3 />
        </Suspense>
      </ErrorBoundary>
    </>
  )
}

const ChildContent1 = async () => {
  await new Promise((resolve) => setTimeout(resolve, 1000))
  return (
    <>
      <p>Counter children 1</p>
      <Suspense fallback="<p>Loading...</p>">
        <ChildContent2 />
      </Suspense>
    </>
  )
}

const Children = async () => {
  return (
    <Suspense fallback="<p>Loading...</p>">
      <ChildContent1 />
    </Suspense>
  )
}

export default createRoute((c) => {
  const name = c.req.query('name') ?? 'no name'
  return c.render(
    <div class={className}>
      <h1>Hello, {name}!</h1>
      <Counter>
        <Children />
      </Counter>
    </div>,
    { title: name }
  )
})

@yusukebe
Copy link
Member

yusukebe commented Feb 16, 2024

@berlysia !

I've released v0.1.2, which supports that it can pass children to islands/client components (including Suspense!) thanks to @usualoma . Could you try it?

@usualoma
Copy link
Member

Oops, forgot to get the attribute values!
I'll fix that right away.

@berlysia
Copy link
Contributor Author

Great. The fix works for my site locally. I'm waiting for merge and publish.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants