To use Emotion with Next.js, you need to set up Emotion correctly to handle server-side rendering (SSR) and client-side hydration. The hydration error occurs when there is a mismatch between the styles rendered on the server side and the client side, leading to React warnings or errors.
Follow these steps to use Emotion with Next.js and avoid hydration errors:
Install Dependencies:
Install the required packages for Emotion and Next.js:
bashnpm install @emotion/react @emotion/server @emotion/styled emotion @emotion/babel-preset-css-prop
Create a Custom Document:
Next.js uses a custom
_document.js
file to handle the server-side rendering. Create the_document.js
file in thepages
directory if it doesn't exist and set it up as follows:jsx// pages/_document.js import Document, { Html, Head, Main, NextScript } from 'next/document'; import { extractCritical } from '@emotion/server'; export default class MyDocument extends Document { static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx); const styles = extractCritical(initialProps.html); return { ...initialProps, styles: ( <> {initialProps.styles} <style data-emotion-css={styles.ids.join(' ')} dangerouslySetInnerHTML={{ __html: styles.css }} /> </> ), }; } render() { return ( <Html> <Head /> <body> <Main /> <NextScript /> </body> </Html> ); } }
This custom document setup captures the CSS generated by Emotion on the server side and injects it into the page as inline styles. This ensures that the same styles are used during server-side rendering and client-side hydration.
Configure Babel:
Ensure that you have the
@emotion/babel-preset-css-prop
preset configured in your.babelrc
file orbabel.config.js
. This preset is needed to properly handle Emotion'scss
prop.Example
.babelrc
:json{ "presets": ["next/babel", "@emotion/babel-preset-css-prop"] }
Wrap the
pages/_app.js
Component:In the
_app.js
file, wrap your Next.js app with theEmotionCacheProvider
to handle client-side hydration:jsx// pages/_app.js import { CacheProvider } from '@emotion/react'; import createCache from '@emotion/cache'; const cache = createCache({ key: 'css', prepend: true }); cache.compat = true; function MyApp({ Component, pageProps }) { return ( <CacheProvider value={cache}> <Component {...pageProps} /> </CacheProvider> ); } export default MyApp;
Wrapping your app with
CacheProvider
ensures that the same Emotion cache is used during client-side rendering, preventing hydration errors.
Now, with Emotion set up correctly, you should be able to use Emotion's styling features in your Next.js components without encountering hydration errors. The server-side rendered styles will match the client-side hydrated styles, ensuring a smooth and consistent user experience.