denoland / fresh

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

Error: Hook can only be invoked from render methods #1540

Open mindon opened 1 year ago

mindon commented 1 year ago

If merging handler and render with a async render using hook, error throwed

here's the example in Multiple Sibling Islands with Shared State https://fresh.deno.dev/docs/examples/sharing-state-between-islands

export default async function Home() {
  const sliderSignal = useSignal(50);
  // ...
}

Error: Hook can only be invoked from render methods

[UPDATE] In this case, using Independent Islands example should be the proper way (error comes from that the handler part run on the server)

deer commented 1 year ago

A very minimal reproduction is:

import { useSignal } from "@preact/signals";

export default async function Home() {
  const sliderSignal = useSignal(50);
  return "hi";
}

This works fine:

import { useSignal } from "@preact/signals";

export default function Home() {
  const sliderSignal = useSignal(50);
  return "hi";
}
marvinhagemeister commented 1 year ago

Yup, under the hood async route components aren't really components but rather a function that happens to return JSX. Because of the missing component instance hooks don't work. Support for proper async components is currently in the works, but needs a bit more time to cook.

uptownhr commented 2 months ago

@marvinhagemeister any update on if this is a roadmap?

lishaduck commented 2 months ago

any update on if this is a roadmap?

from #2363:

The good news is that Preact recently added support for rendering async components on the server itself. This means we can finally drop our workaround and support rendering async components natively.

// Fresh 2.x async components just work
export default async function Page(ctx: FreshContext) {
  // Works as expected in Fresh 2.0
  const value = useContext(MyContext);
  // ...
}

This isn't restricted to just route components either. With the exception of islands or components used inside islands, any component on the server can be async in Fresh 2. Components in islands cannot be async, because islands are also rendered in the browser and Preact does not support async components there. It's unlikely that it will in the near future either as rendering in the client is much more complex, given that it mostly has to deal with updates which are not a thing on the server.

marvinhagemeister commented 2 months ago

We .. err might walk back on that one. Async components are supported in Preact, but not with hooks and it turns out it's a hell to do so without a custom transpile pass. So we're likely not shipping that in Fresh 2. Been meaning to write an update on the current state of things in the Fresh 2 roadmap thread.