I use zustand
to manage my states.
I persist the width state in user local storage then reload and in console, I see an error like this :
Prop
style
did not match. Server: "width:400px" Client: "width:385px"
It's because the default state is 400, but it is 385 in client local storage and when it loads it makes conflict
it gets worst when i try to persist a state that mount & unmount a component because default server state is mount but client state is unmount and it makes client crash
Update July 2024.
I removed if (typeof window === "undefined") return;
in useEffect
because statements in useEffect
run only in browser.
In my case, this answer helps.
https://github.com/vercel/next.js/issues/7417#issuecomment-660241345
When React do the rehydration phase, if the output rendered in the server side is different from the generated in the rehydration phase this makes React be confused and makes him render the output in a wrong way, so what you need to do is assure that the output generated by the server be exactly the same to the generated by the rehydration phase (that have access to browser apis, this is the reason why the output differs) and wait for the component to mount, that happens after the rehydration phase to make any changes based in-browser API or any other type of client-side data
Mind that initial state must be always same between server side and client side, and you can safely change the client side state (and react tree) after the component is mounted.
import { useState, useEffect } from "react";
// default width for SSR
const defaultWidth = 400;
const useWidth = () => {
const [width, setWidth] = useState(defaultWidth);
// onMounted
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return width;
};