hono icon indicating copy to clipboard operation
hono copied to clipboard

feat(jsx/dom): improve compatibility with React

Open usualoma opened this issue 1 year ago • 2 comments

#2508

What is this?

Improve compatibility with React and make the Getting started level code work for the following UI components

https://github.com/honojs/hono/assets/30598/c86423d3-90d0-4296-8ae4-ff90a5432188

by https://github.com/usualoma/hono-react-compat-demo

Simple usage

tsconfig.json https://github.com/usualoma/hono-react-compat-demo/blob/main/tsconfig.json#L22-L28

vite.config.ts https://github.com/usualoma/hono-react-compat-demo/blob/main/vite.config.ts#L5-L8

You can use /hono/jsx

It is better to use hono/jsx/dom in terms of performance, but simply specifying hono/jsx works just as well.

tsconfig.json

   "paths": {
      "react": ["./node_modules/hono/dist/jsx"],
      "react-dom": ["./node_modules/hono/dist/jsx/dom"],
    },

vite.config.ts

    alias: {
      'react': 'hono/jsx',
      'react-dom': 'hono/jsx/dom',
    },

New staffs

The following React compatible staffs are now exported from hono/jsx and hono/jsx/dom

  • createRef
  • forwardRef
  • useImperativeHandle
  • useSyncExternalStore

These staff are also exported from hono/jsx/dom.

  • flushSync
  • createPortal

Children

Implement Children API

https://react.dev/reference/react/Children#alternatives

CSS custom properties in style attribute

CSS custom properties can now be exported.

<div style={{"--my-custom-property": "10px"}}>{children}</div>

defaultProps

defaultProps is an old API, but there seems to be a library that uses it, so it is supported

https://legacy.reactjs.org/docs/react-component.html#defaultprops

Bug fixes

Various bugs have been fixed, such as the behaviour when deleting Elements.

Compatibility with [email protected]

There are no breaking changes from v4.2.7. However, the internal structure has been significantly refactored and there is a possibility of unintended incompatible behaviour, so please check the behaviour of your application when updating.

Author should do the followings, if applicable

  • [x] Add tests
  • [x] Run tests
  • [x] yarn denoify to generate files for Deno

usualoma avatar Apr 24 '24 11:04 usualoma

@usualoma

Coooool! I've tried your repo, it works great!

yusukebe avatar Apr 25 '24 22:04 yusukebe

@yusukebe Thanks for confirming. Tests have been added and are ready for merging!

usualoma avatar Apr 25 '24 23:04 usualoma

Hi @usualoma !

I'll merge this into the "next" branch! The next minor version will be released soon.

yusukebe avatar Apr 30 '24 11:04 yusukebe

Was able to integrate https://ui.shadcn.com/docs/components/calendar#form as an island with the above setup and 4.3.6. Picking works. The toast part doesn't yet.

timurxyz avatar May 13 '24 20:05 timurxyz

I might horribly be disoriented if the below is a missing piece, but let me share my poc:

attachReactJsxNode.tsx:

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(() => {
    console.log('mounting a react-like component')
    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\./, '_') }

UPD: renamed from mount... to attach... which is more browser-like, plus mount is already used by hono in a different context

Demo

From: https://ui.shadcn.com/docs/components/tooltip In islands:

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

export default function TtDemo () {

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

  return attachReactJsxNode(tt)
}

(I still struggle with styles, but that must be my parallel tailwindcss v4-alpha experiments.)

timurxyz avatar May 14 '24 17:05 timurxyz

Hi @timurxyz

If you still think you want the feature/fix, can you create another issue?

yusukebe avatar May 17 '24 02:05 yusukebe

My experiment with getting tamagui to show at least a button in the faked react was blocked by the currently missing useInsertionEffect.

timurxyz avatar May 20 '24 12:05 timurxyz

OK, I'll take a look.

tooltip, useInsertionEffect

usualoma avatar May 20 '24 13:05 usualoma

Hi @timurxyz

If you still think you want the feature/fix, can you create another issue?

2757

timurxyz avatar May 21 '24 14:05 timurxyz