Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hook states get lost with Suspense? #3121

Closed
dios-david opened this issue Apr 20, 2021 · 3 comments
Closed

Hook states get lost with Suspense? #3121

dios-david opened this issue Apr 20, 2021 · 3 comments

Comments

@dios-david
Copy link

I'm migrating a project from React to Preact and I noticed a weird difference in prepass during SSR. I know Preact is not guaranteed to be fully compatible with React, so maybe this is not a bug at all :)

But looks like ref values get lost when using Suspense on SSR. Take this component as an example:

const App = () => {
  const initialised = useRef(false);

  console.log("initialised", initialised.current);

  if (!initialised.current) {
    initialised.current = true;
  }

  const [{ data }] = useQuery({
    query: `
      {
        country(code: "HU") {
          name
        }
      }
    `
  });

  return <span>{data.country.name}</span>;
};

What happens here is when the component is getting rendered in prepass:

  1. Component sets initialised ref to true (it's false by default)
  2. useQuery uses Suspense, so it throws a promise while it's fetching
  3. Once the promise is resolved, the component gets rendered again
  4. initialised ref value got lost, it's false again (with React it's still true)

To Reproduce (with Preact)

Sandbox with Preact: https://codesandbox.io/s/preact-ref-bug-preact-lswel?file=/src/App.js

  1. Go to http://localhost:3000
  2. Check console in the node app

The output is:

prepass start
initialised false
initialised false
prepass end

Expected behaviour (with React)

Sandbox with React: https://codesandbox.io/s/preact-ref-bug-react-h6ukj?file=/src/App.js

  1. Go to http://localhost:3000
  2. Check console in the node app

The output is:

prepass start
initialised false
initialised true
prepass end

Let me know if you need more details!

@JoviDeCroock
Copy link
Member

After taking a deeper look into react-ssr-prepass and react when it comes to Suspense I've found the following to be the case:

When React suspends on initial mount it will erase hookState in progress and retain hookState on subsequent Suspensions.
React-ssr-prepass keeps hookState around so one of the assumptions we do in compat doesn't hold up

@JoviDeCroock
Copy link
Member

This issue will be fixed by preactjs/preact-ssr-prepass#24

@dios-david
Copy link
Author

Thank you @JoviDeCroock for digging into this and fixing it! 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants