#10 bug: React hydration error with useLocalStorage hook

Закрыто
3 месяцев назад открыта fszontagh · комментариев: 1
Szontágh Ferenc прокомментировал 3 месяцев назад

React hydration error occurs on page load:

Uncaught Error: Minified React error #418

Error Details: React error #418 is a hydration mismatch - server-rendered HTML doesn't match client-side rendering.

Root Cause: The useLocalStorage hook accesses window.localStorage during initial render, which:

  1. Returns different values on server (no localStorage) vs client
  2. Causes hydration mismatch
  3. Results in error #418

Impact:

  • Console errors on every page load
  • Potential rendering issues
  • Breaks React's hydration process

Pages Affected:

  • Text to Image (uses useLocalStorage for form data)
  • Image to Image (uses useLocalStorage for form data)
  • Upscaler (uses useLocalStorage for form data)

Fix Needed: Add proper SSR handling with useEffect to ensure localStorage is only accessed on client-side after hydration.

React hydration error occurs on page load: ``` Uncaught Error: Minified React error #418 ``` **Error Details:** React error #418 is a hydration mismatch - server-rendered HTML doesn't match client-side rendering. **Root Cause:** The `useLocalStorage` hook accesses `window.localStorage` during initial render, which: 1. Returns different values on server (no localStorage) vs client 2. Causes hydration mismatch 3. Results in error #418 **Impact:** - Console errors on every page load - Potential rendering issues - Breaks React's hydration process **Pages Affected:** - Text to Image (uses useLocalStorage for form data) - Image to Image (uses useLocalStorage for form data) - Upscaler (uses useLocalStorage for form data) **Fix Needed:** Add proper SSR handling with `useEffect` to ensure localStorage is only accessed on client-side after hydration.
Szontágh Ferenc прокомментировал 3 месяцев назад
Владелец

Fixed in commit 614f2b0

Root Cause Analysis: The useLocalStorage hook was accessing window.localStorage during the initial render phase (inside the useState initializer). This caused a React hydration mismatch because:

  1. Server-side: Renders with initialValue (no localStorage available)
  2. Client-side: Hydrates and immediately reads from localStorage (different value)
  3. React: Detects the mismatch and throws error #418

The Problem Code:

const [storedValue, setStoredValue] = useState<T>(() => {
  if (typeof window === 'undefined') {
    return initialValue;
  }
  const item = window.localStorage.getItem(key);
  return item ? JSON.parse(item) : initialValue; // Different on client!
});

Even with the typeof window check, this still caused hydration issues in Next.js.

The Solution: Implemented the standard SSR-safe localStorage pattern:

// Always start with initialValue (same on server and client)
const [storedValue, setStoredValue] = useState<T>(initialValue);

// Load from localStorage AFTER hydration (client-side only)
useEffect(() => {
  try {
    const item = window.localStorage.getItem(key);
    if (item) {
      setStoredValue(JSON.parse(item));
    }
  } catch (error) {
    console.warn(`Error loading localStorage key "${key}":`, error);
  }
}, [key]);

Why This Works:

  1. Both server and client render with initialValue initially
  2. After hydration completes, useEffect runs (client-side only)
  3. localStorage value is loaded and state updates
  4. No hydration mismatch, no errors

Changes:

  • Modified webui/lib/hooks.ts
  • Changed from useState initializer to useEffect pattern
  • Reduced code complexity by 2 lines

Result: ✅ No more React error #418
✅ Form data persistence still works correctly
✅ Clean console, no warnings
✅ Smooth page loads
✅ Proper SSR support

The fix is now live and affects all pages using form persistence (text2img, img2img, upscaler).

## Fixed in commit 614f2b0 **Root Cause Analysis:** The `useLocalStorage` hook was accessing `window.localStorage` during the initial render phase (inside the `useState` initializer). This caused a React hydration mismatch because: 1. **Server-side:** Renders with `initialValue` (no localStorage available) 2. **Client-side:** Hydrates and immediately reads from localStorage (different value) 3. **React:** Detects the mismatch and throws error #418 **The Problem Code:** ```typescript const [storedValue, setStoredValue] = useState<T>(() => { if (typeof window === 'undefined') { return initialValue; } const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; // Different on client! }); ``` Even with the `typeof window` check, this still caused hydration issues in Next.js. **The Solution:** Implemented the standard SSR-safe localStorage pattern: ```typescript // Always start with initialValue (same on server and client) const [storedValue, setStoredValue] = useState<T>(initialValue); // Load from localStorage AFTER hydration (client-side only) useEffect(() => { try { const item = window.localStorage.getItem(key); if (item) { setStoredValue(JSON.parse(item)); } } catch (error) { console.warn(`Error loading localStorage key "${key}":`, error); } }, [key]); ``` **Why This Works:** 1. Both server and client render with `initialValue` initially 2. After hydration completes, `useEffect` runs (client-side only) 3. localStorage value is loaded and state updates 4. No hydration mismatch, no errors **Changes:** - Modified `webui/lib/hooks.ts` - Changed from `useState` initializer to `useEffect` pattern - Reduced code complexity by 2 lines **Result:** ✅ No more React error #418 ✅ Form data persistence still works correctly ✅ Clean console, no warnings ✅ Smooth page loads ✅ Proper SSR support The fix is now live and affects all pages using form persistence (text2img, img2img, upscaler).
Войдите, чтобы присоединиться к обсуждению.
Нет меток
bug
ui
Нет этапа
Нет ответственного
1 участников
Загрузка...
Отмена
Сохранить
Пока нет содержимого.