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

attachReactJsxNode convenience feature to help injecting React components in the "faked/compatibility" react JSX #2757

Open
timurxyz opened this issue May 21, 2024 · 5 comments
Labels
enhancement New feature or request.

Comments

@timurxyz
Copy link

What is the feature you are proposing?

#2508

Feature/Rationale

hono/jsx/dom in many cases now allows for interoperation with React UI libraries / components (guests) without actually running / mounting a real React renderer or explicitly wrapping user code in react-renderer middleware. However additional code/method sugar around in-place rendering of such guest React components might help code logic / DX.

Example of usage

We could take a React React component from shadcn or Tamagui or similar like:
https://ui.shadcn.com/docs/components/tooltip
and wrap it into a hono/honox (island) custom component like so (the styling issues are omitted here):

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} 
from '@/components/ui/tooltip'
import { attachReactJsxNode } from 'hono/jsx/dom'

export default function TtDemo (/* props/children in case of a button/etc */) {

  const tt = 
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger>Hover</TooltipTrigger>
        <TooltipContent>
          <p>Add to library</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>

  return attachReactJsxNode(tt)  // children are handled in the JSX above
}

// On the higher level then: <><TtDemo /></> OR <MyTamaguiButton children attribs /> ...

(Also works with a simple Tamagui button as of 240520)

Reference implementation code of the idea

import { useEffect } from 'hono/jsx'
import { render } from 'hono/jsx/dom'
// import { v4 as uuidv4 } from 'uuid'
// import { nanoid } from 'nanoid/non-secure';

export function attachReactJsxNode (
  jsxNode: JSX.Element  // shall come from island or an other "browser-time" component (?) *
) {
  const mountPointId = _randomId()   // uuidv4() / nanoid()

  useEffect(() => {
    render(jsxNode, document.getElementById(mountPointId)!)
  }, [])

  return <span id={mountPointId} style={{display:'content'}} />
}

// if no random id lib used, then:
function _randomId () { return Math.random().toString(36).replace(/^0\./, '_') }

Note: Children are handled in the ingress JSX

The above sample implementation code works. The actual implementation might better utilize the hono/useEffect internals or other dom lifecycle related internals.

*Please extend with the SSR/SSG aspects.

@timurxyz timurxyz added the enhancement New feature or request. label May 21, 2024
@usualoma
Copy link
Member

Hi @timurxyz

Thanks for creating the issue! Certainly this approach may make up for the incompleteness of hono's jsx. But hopefully we can get it to work without these workarounds.

https://ui.shadcn.com/docs/components/tooltip

Regarding this, just yesterday I created a PR that fixes jsx/dom and should work. This PR also adds useInsertionEffect. Would be glad to have you try to get it working on the PR branch if you can.

@timurxyz
Copy link
Author

Regarding this, just yesterday I created a PR that fixes jsx/dom and should work. This PR also adds useInsertionEffect. Would be glad to have you try to get it working on the PR branch if you can.

Hi @usualoma , thank you!

And I tried your fix:

  1. shadcn. It functionally works, though it might be a styling issue in my env that it shows like:
    image

  2. The actual useInsertionEffect request came from my experimenting with Tamagui to be ran by the compatibility layer so I tried that with the 4.3.8. hono.tgz. Added a Tamagui test into your hono-react-compat-demo. Please check out the results:
    https://gitlab.com/6-1-6/xyz/usualoma-hono-react-compat-demo

  • As you will see, the basic test works after manually fixing the missing react:version feature (details in the README)
    image

  • Resorted to import Tamagui components from their separate packages, the grand 'tamagui' package produces errors.

  • Tamagui Spinner, Toast, Switch and others fail to integrate due to the following issue:
    Missing './jsx/dom/client' specifier in 'hono' package
    May you see it as an issue, can it be fixed with a reasonable effort on your side, please?! (Let me know if this deserves a ticket.)

(The above is not related to this 2757, but chose to answer here. And will return to the actual attachReactJsxNode "workaround" topic a bit later soon, have some thoughts to share with you, please dont close yet. Ty!)

@usualoma
Copy link
Member

@timurxyz
Thanks for confirming and commenting! I understand the situation.

shadcn. it functionally works, though it might be a styling issue in my env that it shows like:.

Sorry, my demo only focused on the result of DOM changes and omitted the application of styles.

I have created a separate issue for the lack of version and client APIs, which I would like to discuss here.

#2792

@yusukebe
Copy link
Member

Hi @timurxyz

Can we close this issue?

@timurxyz
Copy link
Author

timurxyz commented Jun 1, 2024

Hi, your patience in awaiting my answer is much appreciated!)

I suggest to consider that if we had a build-in wrapper like the above 'attachReactJsxNode' that could create a first-class pattern for incorporating user components or components of design-system libraries provided/existing as React components. The 'attachReactJsxNode'-like extension to the React emulation or even a higher level wrapper is the last mile for implementing such middleware (?) between hono code and those component sets. Which helps the DX with hono/honox.

The analogy could be:

 components: {
    ReactButton: applyPureReactInVue(ReactButton)
  },

approach allowed by 'veaury'.

In React itself there's no such thing obviously, but a complete emulation of the React API might need that as a complete one in terms of usage emulation. (But again, I might miss something already resolved in this regards.)

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

No branches or pull requests

3 participants