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

feat: render children #56

Merged
merged 11 commits into from
Feb 16, 2024
Merged

feat: render children #56

merged 11 commits into from
Feb 16, 2024

Conversation

usualoma
Copy link
Member

What is this?

It enables the execution of Server and Client Composition Patterns in Next.js, allowing the client component to pass children (already processed on the server side).

https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns

"createChildren" New option

In this PR, the contents of children are written once to a template element, which must then be converted to an element generated by createElement. The conversion is performed by createChildren.

If you are using jsx of hono as is, or only simple children without Suspense or ErrorBoundary, you do not need to specify createChildren.

If you are using something like react and want to define your own createChildren, you can specify as follows

createClient({
  hydrate: async (elem, root) => {
    const { hydrateRoot } = await import('react-dom/client')
    hydrateRoot(root, elem)
  },
  createElement: async (type: any, props: any) => {
    const { createElement } = await import('react')
    return createElement(type, props)
  },
  createChildren: async (childNodes: NodeListOf<ChildNode>) => {
    const { createElement } = await import('react')
  
    const create = (childNodes: NodeListOf<ChildNode>): ReturnType<CreateChildren> => {
      const children = [];
      for (let i = 0; i < childNodes.length; i++) {
        const child = childNodes[i] as HTMLElement;
        if (child.nodeType === 8) {
          // skip comments
          continue;
        } else if (child.nodeType === 3) {
          // text node
          children.push(child.textContent);
        } else {
          children.push(
            createElement(child.nodeName, {
              children: create(child.childNodes),
            })
          );
        }
      }
      return children as any;
    }
  
    return create(childNodes);
  }
})

Required PR

For this PR to work, the following PR must be merged with the following HONO and the HONO version in this PR must be bumped.

honojs/hono#2216

For a more detailed explanation, simple children and Suspense work without PR; ErrorBoundary requires PR.

Demo

If you npm run dev on the following project, you will see the following demo.

https://github.com/usualoma/honox-jsx-children

ServerClientComponents.mp4

@yusukebe
Copy link
Member

Hello @usualoma !

This is super cool! I thought the code was a little large, but I don't think it's a problem because it's easy to read.

Looks good! So, I'd like to merge this. Can you resolve the conflict and fix the test error?

@yusukebe
Copy link
Member

@usualoma

honojs/hono#2216 is already merged, and I've added the new version of honor as devDependencies in #59.

@usualoma
Copy link
Member Author

@yusukebe
resolved conflict at b7925ff!

a little large

Well, we certainly don't need this code when the app doesn't use children.

Sorry to add this after the review, but how about adding b1591a2: buildCreateChildrenFn is dynamically imported only when using "children". (It's slight, but it reduces about 1kB.) If we don't need it, I will revert b1591a2.

Also hono 4.0.3, but if you don't remove and rebuild "bun.lockb", 4.0.0 will be installed forever, so I rebuilt it. af20da4 Please point out any problems. (b7925ff is failing the test because of it.)

@yusukebe
Copy link
Member

@usualoma

Sorry to add this after the review, but how about adding b1591a2: buildCreateChildrenFn is dynamically imported only when using "children". (It's slight, but it reduces about 1kB.) If we don't need it, I will revert b1591a2.

Ah, yes, now we can use Dynamic Import on the client side. Let's go with this.

I'll merge it and will release a "patch" version that includes it (HonoX is currently alpha phase, so we don't follow the semver). Thanks!

@yusukebe yusukebe merged commit 63ee1bf into honojs:main Feb 16, 2024
1 check passed
@usualoma usualoma deleted the feat/hydrate-children branch April 26, 2024 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants