denoland / fresh

The next-gen web framework.
https://fresh.deno.dev
MIT License
12.23k stars 622 forks source link

Trouble trying to use react libraries in client islands even with aliases #1491

Open iivvaannxx opened 1 year ago

iivvaannxx commented 1 year ago

The problem

I can understand this is still quite a "new" framework, but I have to say that is a little bit painful trying to integrate some external React libraries with Fresh. Especially when we don't have any piece of documentation on how to do it properly anywhere, at least outside these issues, where everyone seems to have a different working solutions regarding the parameters used in esm.sh import URLs. It would be certainly helpful to have it clearly documented somewhere, even if it's to say that most packages won't work.

My attempts

I tried to integrate 4 different libraries without success, first, it was MUI and then Headless UI, even though I was able to bring some components into my app they wouldn't work as intended or throw some weird errors.

Recently I tried to import 2 different libraries to work with forms, the first one being Modular Forms (which has a preact compatible package) and the second being react-hook-form. For some reason even though I use each and every component or function of these packages in islands exclusively, the JS seems not to work, maybe for some hydration issue?

To be clear, with Modular Forms for some reason my island was being rendered twice, and the error checking/value updating performed by the useForm hook provided by the package wasn't working at all. Then with React Hook Form, even though the values were updating correctly, the submit handlers didn't work, and neither did the error checking with Zod (integrated).

For Modular Forms I had this import map (which was added through deno task esm:add @modular-forms/preact

"@modular-forms/preact": "https://esm.sh/v128/*@modular-forms/preact@0.6.0"

Which I really was looking forward to get it working, but I couldn't, even without the need of aliasing react dependencies.

Then for React Hook Form I had this (also added through deno task esm:add react-hook-form)

"react-hook-form": "https://esm.sh/v128/*react-hook-form@7.45.2?alias=react:preact/compat&external=react"

I don't know if I misread something in esm.sh about how to alias dependencies or I misunderstood how to do it from different issues here but it would certainly be helpful to have a little section in the docs showing how to do it. I may be doing something wrong myself, which could perfectly be the problem, but after trying with many different libraries I am starting to think that is some error during the hydration process.

For the first form library (Modular Forms) I actually prepared a minimal reproduction example because I was thinking of opening a separate issue before I tried React Hook Form (I will be linking it below). For some reason that I can't understand the island gets rendered twice (one of them with an incorrect parent) and the values don't get updated (should be printed just below). The thing that makes me even more confuse is that the same exact code (copy-pasted) works in a CodeSandbox which uses an older version of Fresh, if I am not mistaken.

Example

Reproducible example: https://github.com/iivvaannxx/deno-forms-bug CodeSandbox: https://codesandbox.io/p/sandbox/zealous-ardinghelli-jqztkd

Screenshots

This is the output at the CodeSandbox, as it should behave.

image

And this is the output in the example provided in the repo (created with a brand new Fresh installation and by copy-pasting the code):

image

With this generated code (from DevTools):

image

Additional information

The reproducible repo also contains a Dockerfile which uses my Deno version to package the app. It can be run with the instructions in the README or with deno task start. Funny thing is, if you change the first line from the Dockerfile from

FROM denoland/deno:1.35.1

to

FROM denoland/deno:1.30.3

which is the deno --version output in the CodeSandbox, the problem remains.

The output of deno --version on my machine is:

deno 1.35.1 (release, x86_64-unknown-linux-gnu)
v8 11.6.189.7
typescript 5.1.6
osddeitf commented 1 year ago

This is what I tried:

    "react": "https://esm.sh/preact@10.16.0/compat",
    "react-dom": "https://esm.sh/preact@10.16.0/compat",
    "react-hook-form": "https://esm.sh/react-hook-form@7.43.9&external=react",
iivvaannxx commented 1 year ago

This is what I tried:

    "react": "https://esm.sh/preact@10.16.0/compat",
    "react-dom": "https://esm.sh/preact@10.16.0/compat",
    "react-hook-form": "https://esm.sh/react-hook-form@7.43.9&external=react",

This actually fixes my problem with zod validation, as it correctly validates in realtime the input data. However, react-hook-form has a special handleSubmit method that needs to be passed to the onSubmit event in order for the form state to be as it's expected to be, and doesn't seem to work for me on that end. Whenever I submit the form, nothing happens (it should print to the console).

marvinhagemeister commented 1 year ago

So far it looks like this is a bug in either our island revival code or Preact's hydration code. Don't think this has to do with the react compat layer.

marvinhagemeister commented 1 year ago

The duplicate element issue has been resolved, but the onSubmit is not firing. Need to investigate further.