Next.js Discord

Discord Forum

localStorage not defined in client component

Answered
Savannah posted this in #help-forum
Open in Discord
SavannahOP
I have a component that provides user for every component in my project via context. It is defined like so:

"use client"

import { User } from "@/types/database"
import { createContext, useState } from "react"
import { AuthContextType } from "@/types/contexts"
import { retrievePreviousUser } from "@/lib/database"

export const AuthContext = createContext<AuthContextType>({
  user: null,
  setUser: () => {},
})

function AuthProvider({ children }: {children: React.ReactNode}) {
  const [ user, setUser ] = useState<User | null>(retrievePreviousUser)

  return (
    <AuthContext.Provider value={{user, setUser}}>
        {children}
    </AuthContext.Provider>
  )
}

export default AuthProvider


function retrievePreviousUser accesses localStorage and retrieves user if it's present in the browser memory. However, when site loads I'm receiving this error in the console:

src\lib\database.ts (11:17) @ localStorage
 ⨯ ReferenceError: localStorage is not defined
    at getMeta (./src/lib/database.ts:17:18)
    at retrievePreviousUser (./src/lib/database.ts:51:22)    
    at AuthProvider (./src/components/AuthProvider.tsx:19:76)
   9 |
  10 | function getMeta(): MetaScheme {
> 11 |     const data = localStorage.getItem("meta")


Why is this happening? And even though I'm getting error, it still loads. Just barely flashes error screen for a millisecond.
Answered by Ray
because client component will also be rendered on server so you need to do something like this
 const [meta, setMeta] = useState<string|null>(null);

  useEffect(() => {
    const meta = localStorage.getItem("meta");
    setMeta(meta);
  }, []);
View full answer

9 Replies

@Savannah I have a component that provides **user** for every component in my project via context. It is defined like so: ts "use client" import { User } from "@/types/database" import { createContext, useState } from "react" import { AuthContextType } from "@/types/contexts" import { retrievePreviousUser } from "@/lib/database" export const AuthContext = createContext<AuthContextType>({ user: null, setUser: () => {}, }) function AuthProvider({ children }: {children: React.ReactNode}) { const [ user, setUser ] = useState<User | null>(retrievePreviousUser) return ( <AuthContext.Provider value={{user, setUser}}> {children} </AuthContext.Provider> ) } export default AuthProvider function `retrievePreviousUser` accesses localStorage and retrieves user if it's present in the browser memory. However, when site loads I'm receiving this error in the console: ts src\lib\database.ts (11:17) @ localStorage ⨯ ReferenceError: localStorage is not defined at getMeta (./src/lib/database.ts:17:18) at retrievePreviousUser (./src/lib/database.ts:51:22) at AuthProvider (./src/components/AuthProvider.tsx:19:76) 9 | 10 | function getMeta(): MetaScheme { > 11 | const data = localStorage.getItem("meta") Why is this happening? And even though I'm getting error, it still loads. Just barely flashes error screen for a millisecond.
because client component will also be rendered on server so you need to do something like this
 const [meta, setMeta] = useState<string|null>(null);

  useEffect(() => {
    const meta = localStorage.getItem("meta");
    setMeta(meta);
  }, []);
Answer
SavannahOP
Hmm. Why would it need to do that? Is it alright that it will always return null on server?
For example, it doesn't try to render client components with useState or useEffect on server
Why it does this when I'm accessing localStorage?
@Savannah For example, it doesn't try to render client components with `useState` or `useEffect` on server
it does
SavannahOP
Can you give me a link? I'd read this article
SavannahOP
I thought it just ignores client components on server
Thanks!