From 8d0972a2968d1caf1357d02667bbf6f0116bc4b2 Mon Sep 17 00:00:00 2001 From: Glenn Gijsberts Date: Sun, 6 Feb 2022 23:50:55 +0100 Subject: [PATCH] Make adjustment to cache config of with-apollo example (#32733) ## Description This year we implemented the new Apollo config using this example. We recently moved to `getServerSideProps` as well, however, this was giving us some cache problems. The issue was that the cache was older than the actual data that was coming from the server side query. Because the `merge` of the cache in `apolloClient.js` is merging the existingCache in the initialState it will overwrite the "fresh" initialState with properties that already exists. This means that if you have something in your cache from previous client render, for example `user` with the value `null`, and you go to a new page and do a new query on the server which returns a value for the `user` field, it will still return `null` because of that `merge` function. Since this was weird in our opinion, we've changed this in our own environment by always overwriting the existing cache with the new initialState, so that the initialState that is coming from a fresh server side query is overwriting. We thought it was a good idea to reflect this also in this example, because we couldn't think of a reason why the existing cache should overwrite fresh queries. I've added a reproduction that shows what this is exactly about. I hope my description makes sense, let me know what you think! ## Reproduction of old scenario Created a reproduction branch here: https://github.com/glenngijsberts/with-apollo-example. Using a different API than in the example, because of https://github.com/vercel/next.js/issues/32731. 1. checkout the example 2. yarn 3. yarn dev 4. visit http://localhost:3000/client-only 5. Hit "Update name". This will run a mutation that will update the cache automatically. Because I use a mocked API, the actual value on the API won't be updated, but this is actually the perfect scenario for the problem because in reality data can already change in the meantime when you're doing a new request. 6. Go to the SSR page 7. This will display two values: one is coming from the server side request (which is the latest data, because no cache is used in `getServerSideProps`) and the other is using the cache, which is outdated at that point, yet it's still returned because the old way of merging the cache was picking the existing cache over the initialState that was coming from the fresh server side query. ## Documentation / Examples - [x] Make sure the linting passes by running `yarn lint` --- examples/with-apollo/lib/apolloClient.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/with-apollo/lib/apolloClient.js b/examples/with-apollo/lib/apolloClient.js index 554bcea87ded..b6aa661ce207 100644 --- a/examples/with-apollo/lib/apolloClient.js +++ b/examples/with-apollo/lib/apolloClient.js @@ -36,8 +36,8 @@ export function initializeApollo(initialState = null) { // Get existing cache, loaded during client side data fetching const existingCache = _apolloClient.extract() - // Merge the existing cache into data passed from getStaticProps/getServerSideProps - const data = merge(initialState, existingCache, { + // Merge the initialState from getStaticProps/getServerSideProps in the existing cache + const data = merge(existingCache, initialState, { // combine arrays using object equality (like in sets) arrayMerge: (destinationArray, sourceArray) => [ ...sourceArray,