Skip to content
This repository has been archived by the owner on Jul 28, 2023. It is now read-only.

⚛️ Add Suspense and ErrorBoundary examples #70

Conversation

DAreRodz
Copy link
Collaborator

@DAreRodz DAreRodz commented Sep 16, 2022

I've added two simple examples to check if Suspense and useErrorBoundary work out of the box. Using contexts was already tested, and it works fine, without any problems.

To test error boundaries, I did the following: ✅

  • Added a button inside Interactive Child that makes the render throw an error.
  • Used the useErrorBoundary hook inside Interactive Parent to render a fallback when an error reaches the component. The fallback shows a button to recover from the error.

To test Suspense, I added a lazy-loaded component that renders inside Interactive Child. 🚧

Comment on lines 35 to 41
<Suspense
fallback={
<p key="suspense">
<div>Loading...</div>
</p>
}
>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Suspense wrapper needs to be on the parent block. Otherwise, we are only testing that it works in Preact, aren't we? 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, sure! This is just the first step, which is still not working. 😅

I switched the PR back to a draft.

</p>
}
>
<div key="suspense">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need the key? Is it a Suspense thing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not, I was just testing if I can make Suspense hydration work (see #70 (comment)).

I noticed that even if key could fix the error by making Preact recognize the elements and overwriting it, as key is not serialized during save(), this is not a valid approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use wp-key if necessary and then switch to key in the toVdom (or options.vnode).

Let me know if that helps because I was even thinking that it should be wp-key to make everything related to this hydration prefixed with wp-.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I was just thinking of using a directive for that. Let me try it.

@luisherranz
Copy link
Member

Note here for the future: we need to figure out how this would work with out-of-order hydration. Suspense and ErrorBoundary are even more critical than context. I.e., if we hydrate a children component that throws (an error or a promise) before we hydrate the parent component that catches it (with ErrorBoundary or Suspense) the system may not work as expected.

@DAreRodz
Copy link
Collaborator Author

I'm afraid the Suspense component is not working correctly; it fails during hydration. 😬

Let's say we render the fallback during save(). That's what toVdom() will transform into the initial vDOM.

So, this JSX

<Suspense fallback={<div>Loading...</div>}>
    <LazyParagraph>Hello!</LazyParagraph>
</Suspense>

produces this HTML.

<div>Loading...</div>

Then, when Suspense is hydrated, we have two cases:

  1. the lazy loaded component is still being loaded and cannot be rendered; it renders fallback, and so children once the component is ready.
  2. the lazy loaded component is ready and renders children right away.

Surprisingly, the fallback is preserved in both cases when children is rendered.

<p>Hello!</p>
<div>Loading...</div>

I'll look deeper later to see if we can make this work.

@DAreRodz
Copy link
Collaborator Author

It turns out that Suspense is not rendering the fallback during hydration. 😕

It does, though, if Suspense is rendered after hydration (e.g., using useEffect() to update some state)...

@luisherranz
Copy link
Member

luisherranz commented Sep 19, 2022

I've tested this in isolation, and even though I can't make Suspense work with preact-render-to-string (I'm not sure it supports it), it works fine when I create the SSR manually: https://codesandbox.io/s/sad-poincare-zzrql8?file=/src/index.js

Screen Capture on 2022-09-19 at 11-11-21

I'm not sure what we are doing differently here.

@DAreRodz DAreRodz changed the title Add Suspense and ErrorBoundary examples ⚛️ Add Suspense and ErrorBoundary examples Sep 19, 2022
@luisherranz
Copy link
Member

I'm not sure if I'm doing something wrong, but in isolation, I'm not getting the same behavior with Preact's Suspense as with React's Suspense.

@luisherranz
Copy link
Member

luisherranz commented Sep 19, 2022

@DAreRodz and I were able to reproduce the same behavior on Preact, so it's not something we are doing wrong: https://stackblitz.com/edit/vitejs-vite-r6rhtx?file=src%2Fmain.jsx

It looks like Suspense in Preact is still a bit buggy (it's still an experimental API).

@DAreRodz
Copy link
Collaborator Author

I've removed the Suspense example. We can merge the useErrorBoundary one and try again with Suspense once the API is more stable.

@DAreRodz DAreRodz marked this pull request as ready for review September 20, 2022 10:24
Copy link
Member

@luisherranz luisherranz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@DAreRodz DAreRodz merged commit 2033e25 into main-full-vdom-hydration Sep 21, 2022
@DAreRodz DAreRodz deleted the full-vdom/error-boundary-and-suspense-examples branch September 21, 2022 09:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants