1

I have been checking auth state with localStorage and useEffect and conditional rendering Navbar items according to status. But I get error Warning: Prop href did not match. Server: "/LoginForm" Client: "/Profile". Please help!

export default function App({Component, pageProps}) {
    const authStorage = typeof window !== "undefined" && localStorage.getItem('isAuth')
    const [isAuth, setAuth] = useState(authStorage ?? null)



    useEffect(() => {
        localStorage.setItem("isAuth", isAuth)
    }, [isAuth])


    return (
        <AppContext.Provider
            value={{
                isAuth,
                setAuth
            }}>
            <Layout>
                <Component {...pageProps} />
            </Layout>
        </AppContext.Provider>
    )
}

export default function Nav() {
    const [visible, setVisible] = useState(false);
    const value = useContext(AppContext);
    const router = useRouter()



    

   
    const menuOne = [

        {label: <Link href='/LoginForm'>Log In</Link>, key:'0'},
        {label:<Link href='/RegisterForm'>Sign Up</Link>, key:'1'},

    ]
    const menuTwo=[
        {label: <Link href='/Profile'>Profile</Link>, key:'2'},
        {label:<Link href='/Tickets'>Tickets</Link>, key:'3'},
        {label: <span onClick={Logout}>Logout</span>}
    ]


    return (
        <div className="menu">
            <Link href='/'>

                <div className="logo"/>
            </Link>
            <Menu items={!value.isAuth || value.isAuth === "false" ? menuOne : menuTwo} theme="dark" mode='horizontal' disabledOverflow='true'/>


            <Button className="barsMenu" type="primary" onClick={visible ? onClose : showDrawer}>
                <span className="barsBtn"/>
            </Button>
            <Drawer
                placement="bottom"
                closable={false}
                onClose={onClose}
                open={visible}
                closeIcon
            >
                {!value.isAuth || value.isAuth === 'false' ?
                    (
                        <>
                            <Link href='/LoginForm'>
                                <Button onClick={onClose}>Log in</Button>
                            </Link>
                            <Link href='/RegisterForm'>
                                <Button onClick={onClose}>Sign up</Button>
                            </Link>
                        </>
                    )
                    :
                    (
                        <>
                            <Link href='/Profile' onClick={onClose}>
                                <Button>Profile</Button>
                            </Link>
                            <Link href='/Tickets' onClick={onClose}><Button>My tickets</Button></Link>
                            <div className='logout' onClick={Logout}><span onClick={onClose}><Button>logout</Button></span></div>
                        </>
                    )
                }
            </Drawer>
        </div>

    )
}

Josip Marić
  • 227
  • 4
  • 21

1 Answers1

0

I have made a small example, i think this is the behaviour you need. It keeps the state after refreshing.

_app.js

import { createContext, useContext, useEffect, useState } from "react";
import Nav from "./Nav";

const AppContext = createContext();
export const useAppContext = () => useContext(AppContext);

export default function App({ Component, pageProps }) {
  const [isAuth, setAuth] = useState(false);

  const setAuthAndStore = (bool) => {
    setAuth(bool);
    localStorage.setItem("isAuth", bool);
  }

  useEffect(() => {
    setAuth(localStorage.getItem("isAuth") && localStorage.getItem("isAuth") != "false");
  }, [])

  return (
    <AppContext.Provider
      value={{
        isAuth,
        setAuthAndStore
      }}>

      <Nav />
      <br />
      <Component {...pageProps} />

    </AppContext.Provider>
  )
}

Nav.js

import { useAppContext } from "./_app";

export default function Nav() {
    const { isAuth, setAuthAndStore } = useAppContext();

    return (
        <div className="menu">
            <br />
            <br />

            {!isAuth || isAuth === 'false' ?
                (
                    <>
                        <h1>You need to login</h1>

                        <button onClick={() => {
                            setAuthAndStore(true)
                        }}>Login</button>
                    </>
                )
                :
                (
                    <>
                        <h1>Congrats! You are logged in.</h1>

                        <button onClick={() => {
                            setAuthAndStore(false)
                        }}>Logout</button>
                    </>
                )
            }
        </div>

    )
}
Paulo Fernando
  • 3,148
  • 3
  • 5
  • 21
  • i did figure out that i have a problem with window, but if i set useState default false i will probably get authState false when i refresh page, and i do not want that right? Also i use localStorage here so i don't know how to implement this case here... – Josip Marić Dec 20 '22 at 08:20
  • I edited the answer, check if this helps you – Paulo Fernando Dec 20 '22 at 14:06