Avoiding SSR Pitfalls: Using `next/dynamic` in Your Next.js App
Tags: nextjs, ssr, tip, react
Published: 2023-09-13 13:46:26



## tl;dr

Components wrapped in `dynamic()` as shown below are **not rendered on the server-side** but are exclusively rendered on the client-side.

```typescript
export const PurchaseButton = dynamic(
  Promise.resolve((props: Props) => {
    // Component implementation
  }),
  { ssr: false }
)
```

## The Problem

When components intended for server-side rendering (SSR) are implemented as demonstrated below, discrepancies can arise between Server-side and Client-side rendering, potentially leading to errors during React's hydration phase:

(error message)

```
Unhandled Runtime Error
Error: Text content does not match server-rendered HTML.

See more info here: https://nextjs.org/docs/messages/react-hydration-error
```

Followings are possible causes:

- Adapting rendering based on the presence or absence of the `window` object.
- Content changes based on rendering timing, such as the current date and time.

For more in-depth information, please refer to the following link:

- [Text content does not match server-rendered HTML | Next.js](https://nextjs.org/docs/messages/react-hydration-error)

## How to Address this from the Component Consumer Side

To resolve such issues, one approach is to prevent the targeted component from being rendered on the Server-side.

> **Solution 2: Disabling SSR on specific components**

To achieve this, you can leverage `next/dynamic`. However, in the official documentation, it is often introduced in the context of dynamic imports, possibly with file splitting in mind.

Reference: [Optimizing: Lazy Loading | Next.js](https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading)

```typescript
const DynamicComponent = dynamic(() =>
  import('../components/hello').then((mod) => mod.Hello)
)
```

By following this pattern, the side that utilizes the component (component consumer side) needs to be aware of `next/dynamic`.
If you need the flexibility to toggle between enabling and disabling SSR on a case-by-case basis, that's perfectly fine. However, if the specific component is intended to be non-SSR compliant regardless of its usage context, it's best to handle this within the component itself.

## Addressing the Issue Within the Targeted Component

By wrapping the targeted component entirely with `dynamic(...)`, there's no need for the component consumer to be mindful of SSR considerations. It's worth noting that the first argument of `dynamic()` should be a `Promise<...>`, which typically involves passing the component wrapped in `Promise.resolve()`.

```typescript
export const PurchaseButton = dynamic(
  Promise.resolve((props: Props) => {
    // Component implementation
  }),
  { ssr: false }
)
```

## Conclusion

Server-side rendering (SSR) offers advantages like faster page loads and SEO benefits. Nevertheless, certain components may introduce issues due to disparities between server-side and client-side behaviors.

Through the use of Next.js's `next/dynamic` feature, developers can selectively disable SSR for specific components, ensuring smoother hydration processes and overall enhanced application resilience.

This approach not only provides flexibility in managing components with client-specific dependencies but also streamlines the development process by reducing SSR-related bugs.