Created
January 19, 2018 22:59
-
-
Save bb/a6c9cdbdbe253f3a77c5212c827dc3b1 to your computer and use it in GitHub Desktop.
SSR vs Client State: flicker or fail?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is pages/index.js of a fresh next.js app | |
import {observer} from 'mobx-react'; | |
import {observable} from 'mobx'; | |
const store = observable({ color: "#f00"}) | |
const clientOnly = () => store.color = "#0f0"; | |
if (typeof window != 'undefined') { | |
// clientOnly(); // too early: stays red + console error | |
// Promise.resolve().then(clientOnly); // too early: stays red + console error | |
setTimeout(clientOnly, 0); // too late: red visible | |
// window.requestAnimationFrame(clientOnly); // too late: red visible | |
} | |
export default observer(() => | |
<div style={{background: store.color}}> | |
Background should be green without flickering to red on reload | |
</div>); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Update and solution
If you really, really want to work around flickering and use client side, you can add an inline JS directly in the element. Inside of JSX this needs a little extra work with
dangerouslySetInnerHTML
. I also changed the example to use className, see below for explanation.You may want to add the inline script tag only on SSR - that exercise is left for the reader (-;
Additional info for late client state updates and DOM inconsistencies
You need to make your existing DOM and the client state matching at the time react rehydrates. If client state is updated too late, you need to add
suppressHydrationWarning={true}
on the element you're modifying (i.e. div foo).That may also be needed when you have an inconsistency in output, e.g. when using style instead of classname as in the initial example because of whitespace and color representation (
#0f0
vsrgb(0, 255, 0)
etc.)