react-bootstrap's navbar bug in Nextjs

Recently I started using react-bootstrap with nextjs, and when I use the navBar component, it crashes, I don't know why. When my navbar first loads, it is normal,

enter image description here

but, when I refresh the page, the CSS bugs

enter image description here

and this error appears in the console.

enter image description here

Here is my code:

<Navbar collapseOnSelect expand="lg" bg="danger" variant="dark">
  <Container>
    <Link href="/" passHref>
      <Navbar.Brand>Tecnologia Única</Navbar.Brand>
    </Link>
    <Navbar.Toggle aria-controls="responsive-navbar-nav" />
    <Navbar.Collapse id="responsive-navbar-nav">
      {auth.isLoggedIn && (
        <>
          <Nav className="me-auto">
            <NavDropdown title="Usuários" id="collasible-nav-dropdown">
              <Link href="/users/" passHref>
                <NavDropdown.Item>Listagem</NavDropdown.Item>
              </Link>
              <Link href="/users/create" passHref>
                <NavDropdown.Item>Novo</NavDropdown.Item>
              </Link>
            </NavDropdown>
          </Nav>
          <Nav className={styles.center}>
            <Navbar.Text>Bem-vindo, {auth.user.name}</Navbar.Text>
            <Nav.Link onClick={logoutHandler}>
              <Button variant="outline-light">Sair</Button>
            </Nav.Link>
          </Nav>
        </>
      )}

      {!auth.isLoggedIn && (
        <Nav>
          <Link href="/login" passHref>
            <Nav.Link>
              <Button variant="outline-light">Entrar</Button>
            </Nav.Link>
          </Link>
        </Nav>
      )}
    </Navbar.Collapse>
  </Container>
</Navbar>

Does anyone know why this is happening?

Edit: The auth.isLoggedIn code:

import { createContext, useState, ReactNode } from "react";
import { useRouter } from "next/router";

interface IAuthContext {
  isLoggedIn: boolean;
  token: string | null;
  user: IUserData;
  onLogout: () => void;
  onLogin: (data: LoginData) => void;
}

interface IUserData {
  name: string;
  email: string;
  document: string;
  perfil: number;
}

const AuthContext = createContext<IAuthContext>({
  isLoggedIn: false,
  token: "",
  user: { document: "", email: "", name: "", perfil: 0 },
  onLogout: () => {},
  onLogin: (data: LoginData) => {},
});

type AuthContextProviderProps = {
  children: ReactNode;
};

type LoginData = {
  Id: number | null;
  IsUsuarioAtivo: boolean;
  TipoPerfil: number;
  Token: string;
  Nome: string;
  CPF: string;
  Email: string;
  Login: string | null;
  Perfis: string | null;
  UserIdFB: string | null;
  AccessTokenFB: string | null;
};

export const AuthContextProvider = (props: AuthContextProviderProps) => {
  const router = useRouter();

  let initialToken: string | null = "";
  if (typeof window !== "undefined") {
    initialToken = localStorage.getItem("token");
  }

  const [token, setToken]: any = useState(initialToken);
  const isUserLoggedIn = !!token;

  const [user, setUser]: any = useState<IUserData>({
    document: "",
    email: "",
    name: "",
    perfil: 0,
  });

  const logoutHandler = () => {
    setToken(null);
    localStorage.removeItem("token");
    router.push("/login");
  };

  const loginHandler = (data: LoginData) => {
    console.log(data);
    setToken(data.Token);
    localStorage.setItem("token", data.Token);
    setUser({
      name: data.Nome,
      email: data.Email,
      document: data.CPF,
      perfil: data.TipoPerfil,
    });
    router.push("/");
  };

  return (
    <AuthContext.Provider
      value={{
        user: user,
        token: token,
        isLoggedIn: isUserLoggedIn,
        onLogout: logoutHandler,
        onLogin: loginHandler,
      }}
    >
      {props.children}
    </AuthContext.Provider>
  );
};

export default AuthContext;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 1

Views: 800

Answers (1)

as juliomalves said, placing the inititalToken logic inside a useEffect() hook worked. Obs: I removed the initial token variable, setting the token directly with the localstorage value (the initial state of the token variable now is "")

useEffect(() => {
   setToken(localStorage.getItem("token"));
}, []);

Upvotes: 1

Related Questions