1

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>

3
  • Can you show the part of the code where auth.isLoggedIn comes from? Commented Sep 3, 2021 at 9:08
  • I Edited the post :) Commented Sep 3, 2021 at 14:45
  • The mismatch happens because the initialToken value is different when AuthContextProvider gets executed on the server (it's set to empty string) and when rehydration happens on the client (it's set to localStorage.getItem("token")). Try moving code that should only happen on the client (localStorage access) inside a useEffect instead. Commented Sep 3, 2021 at 14:58

1 Answer 1

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"));
}, []);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.