[go: up one dir, main page]

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: Inconsistency in prefetch behaviour and query.state.dataUpdatedAt values between next versions #6185

Open
1 task done
MlNl-PEKKA opened this issue Nov 1, 2024 · 1 comment

Comments

@MlNl-PEKKA
Copy link
MlNl-PEKKA commented Nov 1, 2024

Provide environment information

System:
OS: macOS 14.1.1
CPU: (10) arm64 Apple M1 Pro
Memory: 59.63 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.10.0 - /usr/local/bin/node
Yarn: 1.22.21 - /usr/local/bin/yarn
npm: 10.2.3 - /usr/local/bin/npm
pnpm: 9.6.0 - /usr/local/bin/pnpm
bun: 1.0.21 - ~/.bun/bin/bun
Browsers:
Chrome: 130.0.6723.92
Safari: 17.1
npmPackages:
@tanstack/react-query: ^5.50.0 => 5.59.16
@trpc/client: ^11.0.0-rc.446 => 11.0.0-rc.608+f75de97b3
@trpc/react-query: ^11.0.0-rc.446 => 11.0.0-rc.608+f75de97b3
@trpc/server: ^11.0.0-rc.446 => 11.0.0-rc.608+f75de97b3
next: ^15.0.1 => 15.0.2
react: ^18.3.1 => 18.3.1
typescript: ^5.5.3 => 5.6.3

Describe the bug

Inconsistency in prefetch behaviour and query.state.dataUpdatedAt values between next versions

Note

I will be adding console logs on the server wherever needed
I will also be setting these query defaults to avoid any client side fetches

       staleTime: 0, 
       refetchOnMount: false,
       refetchOnReconnect: false,
       refetchOnWindowFocus: false,

Redundant prefetches on pages with a prefetch next-15

Due to the changes to the client-side router with latest Next-15 update, pages that had a prefetch in them, re-run on every page request resulting in a bunch of redundant prefetches running on the server and none of the subsequent queries hydrating the client query cache.

382367362-1ba71558-fecc-435d-a93d-08ff44959242.mov

Inconsistency with the query.state.dataUpdatedAt value

I'm unaware of the true implications that this could have but I found this out while debugging the first issue. The query.state.dataUpdatedAt values are inconsistent across versions and environments.

  • Dev server: Next 14.2.16 vs Next 15.0.2:

image
  • Prod server: Next 14.2.16 vs Next 15.0.2:

image

Link to reproduction

https://github.com/MlNl-PEKKA/trpc-test

To reproduce

Replication of Issue 1 :

This issue can be reproduced by trying out the rsc-rq-prefetch demo in the trpc/examples-next-app-dir repository which was upgraded to Next-15, two days ago.

Replication of Issue 2 :

Additional information

More on Issue 1

I am not sure if the subsequent prefetches on navigation are meant to be sent down to the front-end, or even be triggered again in the first place.

Although, I think this new behaviour could be helpful if the prefetched query is sent down and hydrated in the front-end. Which lead me down a path to get this behaviour to work. My initial plan was to the set the default garbage collection time to 0, leading to queries being removed from the cache when there aren't any observers left. This did yield the result and the prefetched queries were successfully hydrating into the client query cache. But this resulted in a horrendous fallback UI to appear on every navigation.

Eventually, I had a look around in react-query docs regarding hydration and came across this limitation regarding hydration. Please correct if I'm wrong. I'm assuming that the HydrateClient component is a wrapper by tRPC around this functionality. This lead me to the next issue.

More on Issue 1 and 2

Initially, tried logging the prefetched queries in the dehydrate option within the createQueryClient function:

image

Again, I'm not sure if this intended, but I believe the query.state.dataUpdatedAt value being 0 could be the reason for the hydration cancellation. I tried the following changes.

export const createQueryClient = () =>
  new QueryClient({
    defaultOptions: {
      queries: {
        staleTime: 0,
        refetchOnMount: false,
        refetchOnReconnect: false,
        refetchOnWindowFocus: false,
        // initialDataUpdatedAt: Date.now(), // <----- Doesn't seem to work,
        // Returns 0 for each query prefetched on a dev server
      },
      dehydrate: {
        shouldDehydrateQuery: (query) => {
          console.log(query.queryHash, "🔥 Before", query.state.dataUpdatedAt);
          query.state.dataUpdatedAt = Date.now(); //             <--------------A workaround for the above
          console.log(query.queryHash, "🔥 After", query.state.dataUpdatedAt);
          return (
            defaultShouldDehydrateQuery(query) ||
            query.state.status === "pending"
          );
        },
        serializeData: transformer.serialize,
      },
      hydrate: {
        deserializeData: transformer.deserialize,
      },
    },
  });

This actually did hydrate into the client query-cache. But it triggered the Suspense fallback, a result similar to the gcTime:0 method.

Screen.Recording.2024-11-02.at.112.59.44.AM-1.mov

👨‍👧‍👦 Contributing

  • 🙋‍♂️ Yes, I'd be down to file a PR fixing this bug!

Funding

  • You can sponsor this specific effort via a Polar.sh pledge below
  • We receive the pledge once the issue is completed & verified
Fund with Polar
@MlNl-PEKKA
Copy link
Author

I’ve been thinking more about this issue, and it feels pretty framework specific. Not sure how much longer I’d like to keep this issue open. Whatever the outcome, I’d really appreciate some clarity on how prefetching, hydration, and suspense work together in this context + patterns and strategies to implement them effectively. If anyone has good resources on this, that’d be much appreciated. It’d really help me (and anybody interested) understand things better, not necessarily for contributing to the tRPC repo itself, but more for the framework example repos and documentation.

@KATT KATT added the 🙋‍♂️ help wanted Extra attention is needed label Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants