Is it possible to enforce an SSR-only mode in Next.js and only partially hydrate the page? Let's say I have this app:
components/dynamic.jsx
export default () => (
<button onClick={() => console.log("I have been clicked")}>Click me</button>
)
pages/index.jsx
import DynamicComponent from "../components/dynamic.jsx";
export default () => (
<div>
<h1>Hello World</h1>
<p>Lorem ipsum</p>
<Hydrate>
<DynamicComponent />
</Hydrate>
</div>
);
Now assume we are rendering pages/index.jsx
with Next.js
so it will be rendered on the server and fully hydrated on the client. For performance reasons (shrink bundle size, reduce execution time) and to have the app play nicer with ads (😒) I only want to hydrate the DynamicComponent
on the client and at best only load the JavaScript for the DynamicComponent
to the client.
Ist that possible with
Thanks
When css-in-js libraries are not set up for pre-rendering (SSR/SSG) it will often lead to a hydration mismatch. In general this means the application has to follow the Next. js example for the library. For example if pages/_document is missing and the Babel plugin is not added.
A hydration mismatch is when the content rendered to HTML in Node. js is not the same than the content rendered in the browser. Hydration mismatches can induce performance degradation and bugs and should therefore be avoided.
getInitialProps is used to asynchronously fetch some data, which then populates props . Data returned from getInitialProps is serialized when server rendering, similar to what JSON.stringify does. Make sure the returned object from getInitialProps is a plain Object and not using Date , Map or Set .
You can do it with a hack:
<>
<StaticContent>
<h1>Hello World</h1>
<p>Lorem ipsum</p>
</StaticContent>
<DynamicComponent />
</>
And the StaticContent
component:
import { createElement, useRef, useState, useEffect } from 'react'
function useStaticContent() {
const ref = useRef(null)
const [render, setRender] = useState(typeof window === 'undefined')
useEffect(() => {
// check if the innerHTML is empty as client side navigation
// need to render the component without server-side backup
const isEmpty = ref.current.innerHTML === ''
if (isEmpty) {
setRender(true)
}
}, [])
return [render, ref]
}
export default function StaticContent({ children, element = 'div', ...props }) {
const [render, ref] = useStaticContent()
// if we're in the server or a spa navigation, just render it
if (render) {
return createElement(element, {
...props,
children,
})
}
// avoid re-render on the client
return createElement(element, {
...props,
ref,
suppressHydrationWarning: true,
dangerouslySetInnerHTML: { __html: '' },
})
}
``
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With