Closed
Description
First off, really nice hook! One issue I'm seeing for SSR'ed apps is if the stored value affects DOM structure then there's going to be a hydration mismatch warning (for example Warning: Expected server HTML to contain a matching <div> in <div>
).
One workaround:
export default function Todos() {
const [query, setQuery] = useState('')
const [todos, setTodos] = useLocalStorageState('todos', ['buy milk'])
// Keep track of whether app has mounted (hydration is done)
const [hasMounted, setHasMounted] = useState(false);
useEffect(() => {
setHasMounted(true)
}, []);
function onClick() {
setTodos([...todos, query])
}
return (
<>
<input value={query} onChange={e => setQuery(e.target.value)} />
<button onClick={onClick}>Create</button>
{/* Only render todos after mount */}
{hasMounted && todos.map(todo => (<div>{todo}</div>))}
</>
)
}
Maybe we can include a section in the readme that covers this? I'm not sure if there's an elegant way for the to hook to handle this. It could wait until mount to return the value from storage, but then that means an extra re-render for non-SSR apps. Thoughts?
More discussion:
https://twitter.com/gabe_ragland/status/1232055916033273858
https://www.joshwcomeau.com/react/the-perils-of-rehydration/
Metadata
Metadata
Assignees
Labels
No labels