Closed chrischen closed 5 years ago
Your hydration is probably working, it's just that the client fetches fresh cache when mounting, see https://github.com/jaydenseric/graphql-react/issues/4 (although the Query
component no longer exists, useGraphQL
has a similar behavior).
Hydrating the data from the server is still important so that the SSR content is not replaced with only loading state when React mounts the components.
As a potential enhancement, cache values could have a new dateFetched
property with a Date
instance denoting when the cache was fetched. That way useGraphQL
could have a new option, cacheExpiresMs
(perhaps a better name) that would be how many milliseconds old cache can be to be reused, otherwise a load()
will fetch fresh cache.
That way if the page load is quicker that the cacheExpiresMs
, cache is reused on the client without a fetch.
ApolloClient seems to have an ssrMode flag that prevents fetching again on initial load.
Cache expiry check Pros:
Cache expiry check cons:
Apollo doesn't fetch when the app mounts in the browser because it doesn't fetch queries when components mount like this library does. Apollo has a lot of issues with stale data as you navigate around an app that this library doesn't.
In the past, I had decided that the client updating it's cache on first mount is a worthwhile tradeoff.
It would be great if there was a way React components could tell that that they are mounting in the browser for the first time after SSR, but I can't think of a way.
What does the current cache do if it always reloads from network?
It doesn't always load from the network; if the useGraphQL
options loadOnMount
is false
it won't.
A central cache is important for lots of reasons.
I already explained that hydrating cache from SSR is important so that when React mounts on the client, the data can be used to cause an identical initial render. Just disable client hydration an you will see the difference: The client will wipe away most of the HTML the server rendered and display only loading states everywhere.
While navigating around your app, cache from the last time the component loaded can be rendered optimistically so the user doesn't always see loading spinners. If the cache that loads is different the component re-renders with the fresh cache.
If you have multiple components with the same query that loads on mount, they will all share one fetch request instead of a request each.
If you have multiple components with the same query that load on demand, loading one will cause cache to render in all of them.
I'm hydrating the cache in the client browser as follows:
window.__GRAPHQL_STATE__
is an object like this:However I'm still seeing the graphql requests hitting the graphql server two times, once on server load and once on client. I've tried disabling the call on client/server code each independently and can confirm it's not simply just running two times.