1

I have a Next.js application where I use @tanstack/react-query@4 for state management and data fetching. I use it for authentication state via a custom useUser() hook that is used throughout the app, including in a nav bar component shared across all pages in a layout component. Let's say I have two identical pages showing me the current user. When I first open my app, everything works fine as the data is shared between the page and the nav bar. Whether I enter page A or B, the observer count for the key ["user"] is 2. The weird thing is that when I navigate to another page and refetch the key, it seems to detach the key from the nav bar, and it stays un-updated (you can see that the observer count is 1). Any advice on how to keep those linked will help!

See in CodeSandbox

Screen Recording

Iftach
  • 95
  • 2
  • 13
  • 1
    See this documentation on how they `useState` I imagine you need to use some code to make sure the new values are propagated through the application when its store is changed. I don't like redux but it is good at that. https://tanstack.com/query/v4/docs/react/guides/ssr – Zach Robichaud Mar 13 '23 at 20:45
  • Check this out. If I had understood the problem right, I might not have. The state is updated in the layout now. https://codesandbox.io/p/sandbox/boring-tristan-xgdhwm – Zach Robichaud Mar 13 '23 at 20:49
  • I updated the example to show the loading state if you wanted it. https://codesandbox.io/p/sandbox/festive-stonebraker-2b1bu2 – Zach Robichaud Mar 13 '23 at 20:59

2 Answers2

3

The problem is you're having an "unstable" QueryClient, as you just create it inside the App component:

export default function App({ Component, pageProps }: AppProps) {
  const queryClient = new QueryClient()

so every time App re-renders, you'll get a new QueryClient. The QueryClient holds the QueryCache, so you throw away cached data, and attached observers etc.

The solution is to keep the client stable, either by moving the instantiation out of the App component, or by putting it into state or an instance ref. For a nextJs application, moving it out of the component is not recommended because it means data might be shared between users when server-rendering. So, as in the docs, this is the solution:

export default function App({ Component, pageProps }: AppProps) {
  const [queryClient] = useState(() => new QueryClient());

Here's a clone of your sandbox with the fixed version

TkDodo
  • 20,449
  • 3
  • 50
  • 65
  • 1
    oh I also have a blogpost on this topic: https://tkdodo.eu/blog/react-query-fa-qs#2-the-queryclient-is-not-stable – TkDodo Mar 20 '23 at 09:32
0

i think that you should pass a props to layout component in the _app page , the pages route provided by nextjs and components folder that we are using for stucturing our projects do not have the same config, that means tha data avaible inside pages will be avaible on your layouts only when you pass them as props , you can fetch the user inside a getStaticProps or Serversideprops (depends on your needs) in your page then the user will be avaible in pageProps inside the _app page, there you can pass your user to your layout as props

1997daly
  • 31
  • 4