I am using Next.js 13 with the App Router and have the following client component, which uses media queries inside the javascript to display a sidebar differently for small/big screens.
"use client";
export default function Feed() {
const [isLargeScreen, setIsLargeScreen] = useState(window.matchMedia("(min-width: 768px)").matches);
useEffect(() => {
window
.matchMedia("(min-width: 1024px)")
.addEventListener('change', e => setIsLargeScreen(e.matches));
}, []);
return (
<div>
<Sidebar isLargeScreen={isLargeScreen}/>
<div>...</div>
</div>
)
}
Now, the site loads inside the client perfectly, but since the Next.js App Router renders this component once on the server and the server has no window
property, I will always get this error on the server (the console running npm run dev
in local development mode):
error ReferenceError: window is not defined
at Feed (./app/feed/page.tsx:32:95)
> 17 | const [isLargeScreen, setIsLargeScreen] = useState(window.matchMedia("(min-width: 768px)").matches);
I can replace the troublesome line with a if-else like this:
const [isLargeScreen, setIsLargeScreen] = useState(typeof window == "undefined" ? true : window.matchMedia("(min-width: 768px)").matches);
which then results in an runtime error on the client, if the server renders the component with the state set to true
, but the client (on a small screen in this example) renders the component with the state set to false
:
Unhandled Runtime Error
Error: Hydration failed because the initial UI does not match what was rendered on the server.
How can change this component so the server and client will not throw any errors?
2
Answers
I think you can use a trick like a "lazy hydration" in Next.js, there is severals methods, for example:
You can create a custom Hook, by creating a new file (useIsLargeScreen?)in the hooks folder :
Than you use this hook on your Feed component:
Another method I think about would be import dynamically your Sidebar, like this:
I’ve seen that it sometimes takes time to get the window object in client components and usually do a recursive check.