Next 14 - localStorage not working after refresh

31 Views Asked by At
'use client';
import {
  Dispatch,
  SetStateAction,
  createContext,
  useEffect,
  useState
} from 'react';

interface ColorsContextProps {
  color: 'blue' | 'green' | 'red' | 'orange' | 'violet';

  setColor: Dispatch<
    SetStateAction<'blue' | 'green' | 'red' | 'orange' | 'violet'>
  >;
}

interface ColorsProviderProps {
  children: React.ReactNode;
}

export const ColorsContext = createContext({} as ColorsContextProps);

export function ColorsProvider({ children }: ColorsProviderProps) {
  const [color, setColor] = useState<
    'blue' | 'green' | 'red' | 'orange' | 'violet'
  >(
    (global?.localStorage?.getItem('preferred_color') as
      | 'blue'
      | 'green'
      | 'red'
      | 'orange'
      | 'violet') ?? 'blue'
  );

  useEffect(() => {
    localStorage.setItem('preferred_color', color);
  }, [color]);

  return (
    <ColorsContext.Provider value={{ color, setColor }}>
      {children}
    </ColorsContext.Provider>
  );
}

I have this code and my localStorage is not available until the client loads. So the state is always set to blue, can anyone know what to do?

I wanted the state to get the localstorage value

1

There are 1 best solutions below

2
Olivier Boissé On

You cannot directly use localStorage to init the state value because as you said localStorage is not available on the server side.

You can init the state with a default value and use an effect to update its value as soon as the app is loaded on client side.

  const [color, setColor] = useState<...>('blue');

  useEffect(() => {
    setColor(localStorage?.getItem('preferred_color') ?? 'blue');
  }, []);

  const contextValue = useMemo(() => ({
    color,
    setColor: newColor => {
      setColor(newColor);
      localStorage?.setItem('preferred_color', newColor);
    }
  }), [color, setColor]);

  return (
    <ColorsContext.Provider value={contextValue}>
      {children}
    </ColorsContext.Provider>
  );