Consider this neat little React hack based off of the useLayoutEffect and useEffect hook.

export const useIsomorphicEffect =
  typeof window !== "undefined" ? useLayoutEffect : useEffect;

Explanation

When React renders your component, useEffect runs client side however useLayoutEffect will run on the server (before browser layout).

This hack is a terrible idea! Do not try to trick React into running an effect on client and server render cycles.

Using both effects can cause the server/client hydration mismatch errors.

I have seen this exact code used in the wild... Do not trust this code!

Instead, I recommend upgrading your code with <Suspense /> and the "use api"

From the React docs:

Replace useLayoutEffect with useEffect. This tells React that it’s okay to display the initial render result without blocking the paint (because the original HTML will become visible before your Effect runs).

Alternatively, mark your component as client-only. This tells React to replace it's content up to the closest <Suspense> boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering.