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(jsx): support class components #1909

Closed
wants to merge 2 commits into from
Closed

Conversation

yusukebe
Copy link
Member

@yusukebe yusukebe commented Jan 6, 2024

Resolves #1907

If we want to implement other methods, it's enough to extend Component, thus only render is implemented.

Author should do the followings, if applicable

  • Add tests
  • Run tests
  • yarn denoify to generate files for Deno

props: Props,
...children: (string | HtmlEscapedString)[]
): JSXNode => {
if (typeof tag === 'function') {
if (typeof tag === 'string') {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It determines if it is a `string to prevent a type warning first.

@yusukebe
Copy link
Member Author

yusukebe commented Jan 6, 2024

Hi @usualoma

What do you think about class components and this implementation?

@usualoma
Copy link
Member

usualoma commented Jan 7, 2024

@yusukebe
I see no problem with the content of this PR.

But before anything else, I think that we should articulate what would make us happy and what problems we would solve if we had a component with state in "hono/jsx" working on the front end.

And I think we should consider how this could be implemented to make it work on the front end.

I would prefer to implement hooks if it becomes necessary to "make hono/jsx work on the front end".

@yusukebe
Copy link
Member Author

yusukebe commented Jan 7, 2024

Hi @usualoma !

Thanks for your comment.

Indeed, we should share what I want to do in front with hono/jsx. I don't have time right now to share just an example.

https://github.com/yusukebe/hono-jsx-front-poc/tree/hono-patched

It's a simple counter sample, the code is rough and could use improvement, but this is the base of what I want to do. Island architecture with server and client referring to the same component, it hydrates when it is displayed and enables interaction.

The class component has update with elements. In the case of JSX without DOM like hono/jsx, I think these two are necessary. This was the easiest way for me to implement this, but I am sure there are other ways.

@usualoma
Copy link
Member

usualoma commented Jan 7, 2024

@yusukebe
Thanks!
I checked out https://github.com/yusukebe/hono-jsx-front-poc/tree/hono-patched. It is a great and easy to understand PoC.
I think I understand the expected results.

My opinion.

  • I think we need to get closer to React behavior if we implement this, and this would require a lot of work. (I think a subset would be sufficient, not a full set of features, but a certain level of compatibility is necessary to the extent it is implemented.)
    • I don't think the current implementation of completely replacing the DOM is sufficient as a feature. If we replace <input type="text"/>, it would be impossible to Ctrl-Z back and the UX would be severely degraded. I think we need to detect and replace the differences.
  • If it can be implemented with a hook, should it be implemented only with a hook? Or, even if it can be implemented with a hook, should it be a class? I would like to discuss this point.

I believe that to release 1.0 of this feature (let's call it Hono Server Components) would require a lot of implementation, including (Tiny?) Virtual DOM, and would be expensive to maintain. While I am not against implementing this feature, I am not convinced that it is really necessary for hono.

What characteristics do you consider Hono Server Components to have?

Also I wrote that I think a Virtual DOM is necessary, but you might think something simpler would be fine. If so, I would be glad to know how simplified you think it should be.

@yusukebe
Copy link
Member Author

yusukebe commented Jan 7, 2024

@usualoma

What characteristics do you consider Hono Server Components to have?

I'm working on a thought on this, so please wait a while.

Here are a few random things to share:

Client Components?

Perhaps it would be better to call them Client Components rather than Server Components. Because the server side of hono/jsx is already completed, and what we are going to work on is the client side.

Nano JSX

I refer to Nano JSX perfectly for the implementation of Client Components. So I used Class Components to implement the interactions. If Nano JSX can do what we want, then following it will not be as hard as React.

https://nanojsx.io/

SPA tradition

Here is another interesting PoC. This one does something similar to React's Server Components with hono/jsx to enable SPA transitions.

https://github.com/yusukebe/hono-jsx-server-components-simple

To make the SPA transition work, in this case, we are sending serialized JSX, but of course, it is also possible to send HTML. It is easier that way.

const renderServerComponent = async (c: Context, element: JSX.Element) => {
  if (c.req.query('__sc') != undefined) {
    return c.html(element)
  }
  return c.render(element)
}

It would be a very interesting idea to add the SPA transition option to the JSX Renderer. We can use either serialized JSX or return partialized HTML, whichever we prefer.

Server Components

I don't think Server Components is a technology only for SPA tradition. It sounds like a dream, but if "functions" written in JSX can be serialized and sent to the client as Server Components, there is no need to go to the trouble of hydration.

htmx

One approach to adding interactions to HTML rendered by hono/jsx is to use htmx.

https://htmx.org/
https://blog.yusu.ke/hono-htmx-cloudflare/

If one were to use htmx aggressively, Client Components would not be necessary. Instead, it would be interesting to have ideas that make it easier to implement applications using htmx, e.g., middleware that returns partials by query or header.


These are only materials for discussion, but they are interesting matters.

@usualoma
Copy link
Member

usualoma commented Jan 8, 2024

@yusukebe
Yes, I agree! I would certainly prefer to call it Client Components.

The following is a crude implementation, but I think it is possible to render "hono/jsx" to "dom" like React.
#1917

I think we can further combine the vite plugin here as follows to make it a client component by simply writing "use client" as in Next.js.
https://github.com/usualoma/hono-dom-hcc

"use client"

import { useState } from 'hono/jsx/hooks'

export const Counter = () => {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>Counter: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  )
}

Nano JSX is great, but I would rather have it work the same way as React than have people learn how to write it differently than React.

@usualoma
Copy link
Member

usualoma commented Jan 8, 2024

PR and demo updated.

hono/css can be used with hono/jsx/dom.

hono-jsx-css.mov

@yusukebe
Copy link
Member Author

yusukebe commented Jan 9, 2024

@usualoma

I've merged #1917 into the v4 branch.

I think we can further combine the vite plugin here as follows to make it a client component by simply writing "use client" as in Next.js.

That is a great PoC. The challenge is how to hydrate Client Components on the server side. Either use use client or use Island Architecture. Since this is a HonoX matter, I'll release an RC version of v4 and test it with it.

Class Components is no longer needed due to the implementation of Hooks, so this PR is closed.

Thanks!

@yusukebe yusukebe closed this Jan 9, 2024
@yusukebe yusukebe deleted the feat/class-component branch May 12, 2024 03:01
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.

Support Class Component
2 participants