UNPKG

opencode-agent-kit

Version:

Multi-stack OpenCode agent toolkit — 33+ specialized AI agents, 200+ skills, 46 commands, 8 MCP servers (Nuxt, React, Node.js, Laravel, CI3, Android, Flutter, DevOps, SEO, SonarQube, and more)

83 lines (67 loc) 2.31 kB
--- title: Prevent Hydration Mismatch Without Flickering impact: MEDIUM impactDescription: avoids visual flicker and hydration errors tags: rendering, ssr, hydration, localStorage, flicker --- ## Prevent Hydration Mismatch Without Flickering When rendering content that depends on client-side storage (localStorage, cookies), avoid both SSR breakage and post-hydration flickering by injecting a synchronous script that updates the DOM before React hydrates. **Incorrect (breaks SSR):** ```tsx function ThemeWrapper({ children }: { children: ReactNode }) { // localStorage is not available on server - throws error const theme = localStorage.getItem('theme') || 'light' return ( <div className={theme}> {children} </div> ) } ``` Server-side rendering will fail because `localStorage` is undefined. **Incorrect (visual flickering):** ```tsx function ThemeWrapper({ children }: { children: ReactNode }) { const [theme, setTheme] = useState('light') useEffect(() => { // Runs after hydration - causes visible flash const stored = localStorage.getItem('theme') if (stored) { setTheme(stored) } }, []) return ( <div className={theme}> {children} </div> ) } ``` Component first renders with default value (`light`), then updates after hydration, causing a visible flash of incorrect content. **Correct (no flicker, no hydration mismatch):** ```tsx function ThemeWrapper({ children }: { children: ReactNode }) { return ( <> <div id="theme-wrapper"> {children} </div> <script dangerouslySetInnerHTML={{ __html: ` (function() { try { var theme = localStorage.getItem('theme') || 'light'; var el = document.getElementById('theme-wrapper'); if (el) el.className = theme; } catch (e) {} })(); `, }} /> </> ) } ``` The inline script executes synchronously before showing the element, ensuring the DOM already has the correct value. No flickering, no hydration mismatch. This pattern is especially useful for theme toggles, user preferences, authentication states, and any client-only data that should render immediately without flashing default values.