reactjsnext.jshydration

Is there a way to detect when render is part of 'hydration'?


Context

I am writing a library that exposes a useQuery hook:

function MyComponent() { 
  const [isLoading, data] = useQuery("query1");
}

useQuery caches data locally. So I could write the following:

function useQuery(q) { 
  const [isLoading, data] = useState(() => {
     if (IndexedDBCache.has(q)) {
       return [false, IndexedDBCache.get(q)]
     }
     return [true];
  });
  useEffect(() => {
    // subscribe to the query...
  })
}

The problem: this will break hydration

If the user uses useQuery in NextJS, it could break hydration.

The server will always return isLoading true, while on the client it's possible the cache kicks in, and returns isLoading: false.

Potential Solution

I could instruct the user to use useQuery only in the client, but I would rather have a more permissive API.

Is there a way I could achieve the following behavior:

  1. If useQuery is called from the server, we always return isLoading: true
  2. If useQuery is called on an initial 'hydration' loop, we always return isLoading: true
  3. But, if useQuery is ever mounted after the hydration loop, we would ask the cache

Solution

  • Turns out, useSyncExternalStore was built exactly for this.