tl;dr
Components wrapped in dynamic()
as shown below are not rendered on the server-side but are exclusively rendered on the client-side.
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:
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
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()
.
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.
Top comments (0)