In the last few years, React has introduced a suite of new features intended to improve server side rendering. These include the <Suspense/> component, the hydrateRoot() API, and the renderToPipeableStream() API. The idea with these is that you should be able to begin a fetch on the server side, but then immediately send a rendered page, with fallback components embedded in it, to the client, and then, once the data has been fetched, pipe the new rendered HTML fragment to the client, where it will be inserted into the DOM at the correct place. Later, once JavaScript has loaded, the page will be hydrated so as to make it interactive. The process is described in this document.
The problem I have is that given the components used on the server side are the same as those on the client side, I can't see how you can write data fetching into these components so that they will fetch on the server side but not again on the client side, at least not in an elegant way.
There is nothing about this in the document I linked to above, or in the React docs that explains this. Indeed, the example from the document, has the data fetching component be a black box, with no explanation of how it works internally:
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
Following, is an example of client side data fetching from a LogRocket blog post that discusses Suspense (though not SSR):
import React from 'react'
import fetchData from '../api/fetchData'
const resource = fetchData(
'https://run.mocky.io/v3/d6ac91ac-6dab-4ff0-a08e-9348d7deed51'
)
const UserWelcome = () => {
const userDetails = resource.read()
return (
<div>
<p>
Welcome <span className="user-name">{userDetails.name}</span>, here are
your Todos for today
</p>
<small>Completed todos have a line through them</small>
</div>
)
}
export default UserWelcome
If this code is rendered on both the server and the client side, the fetch will occur in both places, which is both unnecessary, and in some cases (if the fetch was from an internal database) impossible.
In fact, there's possibly a worse problem is that the hydrated HTML may be different from that produced by the server, since the fetch wont have completed on the client at the time of hydration (possibly).
This seems to me to be a fairly obvious use case, so it's surprising that it's not documented better - or am I missing something?