Skip to content

Does not work with hooks and preact/debug #48

Open
@patdx

Description

I was trying to use react-router, preact and preact-ssr-prepass together and ran into some issues. After eliminating an unrelated ESM/CJS error, I discovered that I was still running into issues with preact-ssr-prepass. It turns out it can be reproduced with a pretty short example:

import 'preact/debug'; // if you comment this line out, it will work
import { h } from 'preact';
import renderToString from 'preact-render-to-string';
import prepass from 'preact-ssr-prepass';

import { useState } from 'preact/hooks';

const App = () => {
  const [x, setX] = useState(10);
  console.log(`Use state inside of App`, x);
  return h('div', undefined, x);
};

const vnode = h(App);

console.log('begin prepass');
await prepass(vnode);
console.log('end prepass');

const out = renderToString(vnode);

console.log(out);

Output:

❯ node index.js
begin prepass
Error: Hook can only be invoked from render methods.
    at async ESMLoader.import (https://node-qpdrhr-230n5kih.w.staticblitz.com/blitz.f2b7d4e326e0543f39833cc6d890b02bb01d7899.js:6:1209283)
    at async i.loadESM (https://node-qpdrhr-230n5kih.w.staticblitz.com/blitz.f2b7d4e326e0543f39833cc6d890b02bb01d7899.js:6:246622)
    at async handleMainPromise (https://node-qpdrhr-230n5kih.w.staticblitz.com/blitz.f2b7d4e326e0543f39833cc6d890b02bb01d7899.js:6:989292)

Here is a stackblitz: https://stackblitz.com/edit/node-qpdrhr?file=index.js


Basically as far as I can tell preact/debug is throwing an error because when the useState() hook is called, hooksAllowed is false. I guess this is related to the timing of the component lifecycle. I think the error from preact/debug seems mistaken because when I comment out that preact/debug import any code I write seems to work fine.

I wonder if this will be fixed by #47? Because it seems that options._diff function will set hooksAllowed = true.

The obvious solution may be to "not use preact/debug on the server side", which I think makes sense. But, in my case I was trying to set up an SSR project with @preact/preset-vite, which has the preact/debug hardcoded in so I never had a choice or knew it was being imported. I'm going to see if I can override it and skip the preact/debug import for the server side render.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions