Suspense
import { Aside } from "~/components/configurable/Aside";
A component that tracks all resources read under it and shows a fallback placeholder state until they are resolved. What makes Suspense different than Show is it is non-blocking in that both branches exist at the same time even if not currently in the DOM. This means that the fallback can be rendered while the children are loading. This is useful for loading states and other asynchronous operations.
1 2 3 4 | |
Here's an example of a Suspense component that shows a loading spinner while the User component is loading.
1 2 3 | |
Nested Suspense¶
{"
For example, in the code below, only the title() resource will trigger the top level suspense boundary, and only the data() resouce will trigger the nested suspense boundary:
1 2 3 4 5 6 7 8 9 10 | |
Understanding the purpose of {""} in Solid:¶
To understand the purpose of suspense, let's consider the following code snippets. These snippets will have some drawbacks which we will solve by using suspense. We will also see how it is possible to use suspense yet not reap its benefits.
Our example use case is to display a user profile. A naive snippet would look like this:
1 2 3 4 5 6 7 8 9 | |
In this code, profile() starts as undefined, and when the fetcher code finishes, resolves to an object with name and email properties. Although the resource has not resolved yet, the two divs are already created and attached to the document body, albeit with empty text nodes. Once the resource resolves, the divs are updated with the appropriate data.
The downside of this approach is that the user is shown an empty component - let's see if we can do better than that in this next snippet:
1 2 3 4 5 6 7 8 9 | |
In this snippet, we first show a fallback when the resource hasn't resolved yet, and then switch to showing the profile data once it has. This results in a better user experience.
On the other hand, there is a slight downside to this approach. In our first example (using optional chaining), the divs were created immediately, and once the resource resolves all that is needed to be done is to fill in the text of the divs. But in our second example (using <Show>), the divs are only created once the resource has resolved, which means there is more work that needs to be done after the resource has resolved before the data can be shown to the user (of course, in this toy example the amount of DOM work is relatively trivial).
We can have the best of both worlds by using {"
1 2 3 4 5 6 7 8 9 | |
In this case, the divs are created immediately, but instead of being attached to the document body, the fallback is shown. Once the resource resolves, the text in the divs is updated, and then they are attached to the document (and the fallback removed).
It is important to note that execution of the component does not pause when using suspense. Instead, when a resource is read under a suspense boundary, it ensures that the nodes are not attached to the document until after the resource has resolved. Suspense allows us to have the best of both worlds: do as much work as we can before the resource resolves, and also show a fallback until then.
With this in mind, we can understand that there isn't much gained from suspense in the following code:
1 2 3 4 5 6 7 8 9 10 11 | |
In this code, we don't create any DOM nodes inside {"<Show>.
Props¶
| Name | Type | Description |
|---|---|---|
fallback | JSX.Element | The fallback component to render while the children are loading. |