fresh icon indicating copy to clipboard operation
fresh copied to clipboard

Error: Hook can only be invoked from render methods

Open mindon opened this issue 2 years ago • 5 comments

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)

mindon avatar Jul 28 '23 09:07 mindon

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";
}

deer avatar Jul 28 '23 10:07 deer

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.

marvinhagemeister avatar Jul 31 '23 07:07 marvinhagemeister

@marvinhagemeister any update on if this is a roadmap?

uptownhr avatar Jun 23 '24 22:06 uptownhr

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.

lishaduck avatar Jun 25 '24 14:06 lishaduck

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.

marvinhagemeister avatar Jun 25 '24 15:06 marvinhagemeister