SolidStart SSR: Why does createAsync data work in JSX but not in a child component?
当然,这是你这段问题的英文翻译,适合用来在 SolidStart 或相关社区中提问:
⸻
In a SolidStart project using SSR, I encountered an issue with a route component that uses createAsync to fetch an async resource. I’ve set deferStream: true, and here’s the problem:
When this route is rendered, some parts of the page correctly display the async data, but some parts (particularly in components) do not render the data properly until I manually refresh the page.
Here’s a simplified version of my component:
The NumberField component comes from solid-ui, which is built on top of Kobalte.
It seems like during client-side hydration, this component doesn’t wait for the async resource to resolve, even though the plain JSX above does. Why does the top part render correctly after the async resource resolves, but NumberField fails unless I refresh the page? Any idea how to ensure proper hydration or data availability across all components?
thanks
4 Replies
You‘ll probably just need to wrap the JSX in Suspense.
✅ Update: I solved it!
Thanks to some digging and experimentation, I figured out the cause and wanted to share the solution here in case anyone else runs into the same issue.
🔍 Root Cause
The issue was related to how createAsync(..., { deferStream: true }) works in combination with components that read props like defaultValue only once during initial mount.
In my case, NumberField from solid-ui was using defaultValue={userProfile()?.data?.height_cm}. But since the data wasn’t available immediately (due to deferred streaming), the component initialized with undefined and never updated later — unless I refreshed the page (which reloaded with the data already present).
✅ Solution
I fixed it by conditionally rendering the component only after the async data was available, like this:
This ensures the component mounts only when the data is ready, so it initializes with the correct value.
Alternatively, if the component supports a controlled mode, you can also use:
📌 Summary
• JSX bindings like <p>{userProfile()?.data?.nickname}</p> are reactive and work fine.
• Some components “freeze” their defaultValue on mount — before the async resource resolves.
• Workaround: delay rendering, or use value for reactive behavior.
Hope this helps future readers! Let me know if you’ve faced something similar or have better workarounds 🙌
yes, that's a common crux on working with anything that uses primitives with default values and async data, because primitives are not reactive context.
e.g.
In solid 2.0 we will be able to pass an accessor to createSignal which will update when the accessor updates which will help in these cases:
thanks. I am looking forward to experiencing solid2.0