Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] 🪳 Fix unwanted re-fetching of data on first page load #1912

Merged
merged 9 commits into from
Jul 23, 2024

Conversation

bendvc
Copy link
Collaborator

@bendvc bendvc commented Jul 18, 2024

Description

Currently the template-retail-react-app uses a staleTime of 10 seconds for React Query. We use this value, in part, to avoid re-fetching data on the first page load.

Unfortunately we have not accounted for cached pages. This means a cached response can be up to 10 minutes old (by default) and the data within the cached responses is almost always stale unless the cached pages is less that 10 seconds old.

This isn't the behaviour we want or had intended. We want the data to be fresh for the 10 seconds as defined in the stale time prop. Meaning the data's dataUpdatedAt should always be the same time the app loads.

In this PR we ensure that we "fudge" the data's timestamp and assign it the datetime that the app of loaded, not the value it was initially fetched.

NOTE: This isn't a great solution so I'm looking for some feedback, below are some alternative solutions that I've looked in to or considered.

  1. Ensure the stale time is longer than the ssr page cache time. (This should effect the user experience after page load as data would stay fresh longer)
  2. Instead of deleting the timestamp we set it to the current time. (This works, but is finicky as it takes time from hydration of the provider to the time the plp requests data, so we almost need a buffer time to add to it)
  3. Use APIs in ReactQuery like prefetchData or initialData and initialDataUpdatedAt (none seemed to do exactly what we wanted)
Screen.Recording.2024-07-19.at.11.47.54.AM.-.2.mov

Lighthouse Scores

Before:

image

After:

image

Note: Score values seemed to be more unpredictable on the pre-fix and were all over the place (probably as sometimes the loading skeleton was shown and sometimes not) on the fixed version they were more consistent.

Types of Changes

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Breaking change (could cause existing functionality to not work as expected)
  • Other changes (non-breaking changes that does not fit any of the above)

Changes

  • Overwrite time stamp for all serialized queries and mutations in the withReactQuery HOC.
  • Added tests.

How to Test-Drive This PR

Checklists

General

  • Changes are covered by test cases
  • CHANGELOG.md updated with a short description of changes (not required for documentation updates)

@bendvc bendvc marked this pull request as ready for review July 19, 2024 21:28
@bendvc bendvc requested a review from a team as a code owner July 19, 2024 21:28
@kevinxh kevinxh self-requested a review July 22, 2024 16:33
kevinxh
kevinxh previously approved these changes Jul 23, 2024
beforeHydrate: (data) => {
const now = Date.now()

// Helper for removing the data timestamp.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is no longer true.

Suggested change
// Helper for removing the data timestamp.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the comment

preloadedState = beforeHydrate(window.__PRELOADED_STATE__?.[STATE_KEY] || {})
} catch (e) {
logger.error('Client `beforeHydrate` failed', {
namespace: 'WithReactQuery render',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have the namespace match our convention... more code like (e.g. no spaces, but can have dots). For example, see

logger.error(cause, {namespace: 'react-rendering.render'})

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the logger to use with-react-query.render

@@ -29,6 +39,49 @@ describe('withReactQuery', function () {
expect(screen.getByText(/Hello world/i)).toBeInTheDocument()
})

test('`beforeHydrate` called on mount', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have tests for the beforeHydrate. Can we also have a test on the retail-react-app too?

Say for a page like PLP, have a test to verify that there is no skeleton and no productSearch refetch. Otherwise, if there's a regression in this behaviour, we can only detect it manually.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we currently have unit test for our a page components, and how those are done is purely run in a client-side manner (e.g. the server side data fetching and rendering is not built into the unit tests). We do have E2E tests that would probably be a better place to home the requests test. Unfortunately all our E2E tests don't access the PLP directly, they simply do things like guest flow and registered flow, meaning the PLP is always a soft navigation.

How married are you to having a one off e2e test to check that skeletons don't show up. It's not a bad idea, but I know we have been talking about having a separate push for uplifting out e2e tests and that might be a goos AC for that work.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created a ticket to create e2e on a broader scope for testing hydration state across the template.

@bendvc bendvc merged commit a35e215 into develop Jul 23, 2024
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants