"The perils of rehydration"

In React apps that use SSR, where your component code can run both on the server and on the client, it's sometimes important to know where your code is currently running.

In "The Perils of Rehydration", Josh Comeau talks about why the following is a problem for rehydration:

const Component = () => { if (typeof window === 'undefined') { return null } // Client-only code return <>...</>; }

And why waiting until after the Component mounts can help avoid rehydration issues:

const Component = () => { const [hasMounted, setHasMounted] = useState(false); useEffect(() => { setHasMounted(true); }, []); if (!hasMounted) { return null; } // Client-only code return <>...</>; }

August 3, 2021 at 2:50 AM

TypeScript utility types

These types can be helpful, especially when working with generated types from APIs.

/** * Make all properties in TType required and non-nullable * @example * Definite<{ foo?: string | null }> // => { foo: string } */ export type Definite<TType> = Required< { [TKey in keyof TType]: NonNullable<TType[TKey]> } >; /** * Same as Pick, but all picked properties are required and non-nullable * @example * PickDefinite<{ bar?: string | null, foo?: string | null, }, 'bar'> * // => { bar: string } */ export type PickDefinite<TType, TKey extends keyof TType> = Definite< Pick<TType, TKey> >; /** * Retrieve the type of a single property from a type or interface * @example * type BarType = Take<{ foo: string, bar?: string }, 'bar'> * // => string | null | undefined */ export type Take<TType, TKey extends keyof TType> = TType[TKey];

July 30, 2021 at 1:00 AM

Why it's important for server and client to match in SSR

I learned some very valuable lessons about SSR and hydration this week. Some people might already have learned these lessons, but I figured I'd share anyway.

Don't ignore that Next warning message:

Warning: X did not match. Server: "<What next rendered on the server>" Client: "<What next rendered on the client>"

It'll probably bite you if you do.

The crux of it is that, in Next, you should try to stay away from manipulating the HTML in such a way that the server's HTML is different than the client's HTML. Especially when it comes to images, but I think it applies to all elements. This will always result in a shift in the page, even if your first client-side render has the correct HTML. As I understand it, it's all about "hydration".

  1. Next runs your React code and renders the HTML on the server. It then sends that HTML down to the client and shows it to the user. Your client-side React code has not run yet at this point but the user still sees your UI.
  2. Next "hydrates" the page with your React code, and then re-renders the page, adjusting any HTML that might've changed now that it is running on the client. This is the first render that happens on the client (i.e., you can expect that any code inside a Component function is run at this point). This is also where you'll see the above warning if any of that HTML that the server rendered doesn't match.
  3. After that first render, all useEffects kick in, and any code inside of them is executed, potentially causing additional renders.

The bold part of Step 1 above is the reason why it's so important not to ignore that warning.

July 25, 2021 at 5:22 PM