在React上下文中保存用户信息,导航栏在登录后显示注销。导航到其他页面时,它显示登录而不是注销

问题描述 投票:0回答:1

这是我用来包装整个应用程序的 AuthProvider 文件

// AuthContext.tsx
import React, { createContext, useContext, useState, ReactNode } from "react";

interface UserData {
  username: string;
  password: string;
  id: string;
  first_name: string;
  last_name: string;
  postal: string;
  email: string;
  telephone_number: string;
}

interface AuthContextProps {
  user: UserData | undefined;
  setUser: (userData: UserData | undefined) => void;
}

export const AuthContext = createContext<AuthContextProps | undefined>(undefined);

export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<UserData | undefined>(undefined);

  const updateUser = (userData: UserData | undefined) => {
    setUser(userData);
  };

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

export const useAuth = (): AuthContextProps => {
  const context = useContext(AuthContext);

  if (!context) { 
    throw new Error("useAuth must be used within an AuthProvider");
  }

  return context;
};

这是您需要检查的导航栏的一部分

export default function Example() {
  const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
  // const { user, setUser } = useAuth();
  const context = useContext(AuthContext);

  return (
    <AuthProvider>
      <header className="bg-gradient-to-r from-blue-50 via-blue-300 to-blue-500">
        <nav
          className="mx-auto flex max-w-7xl items-center justify-between p-0 lg:px-8"
          aria-label="Global"
        >
          <div className="flex lg:flex-1">
            <a href="#" className="-m-1.5 p-1.5">
              <span className="sr-only">Your Company</span>
              <img
                className="h-8 w-auto"
                src={imgLib}
                alt=""
                style={{ width: "170px", height: "170px" }}
              />
            </a>
          </div>
          <div className="flex lg:hidden">
            <button
              type="button"
              className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700"
              onClick={() => setMobileMenuOpen(true)}
            >
              <span className="sr-only">Open main menu</span>
              <Bars3Icon
                className="h-6 w-6 mr-5"
                aria-hidden="true"
                style={{ color: "white" }}
              />
            </button>
          </div>
          <Popover.Group className="hidden lg:flex lg:gap-x-12">
            <a
              href="/home"
              className="text-sm font-semibold leading-6 text-black-900"
            >
              Home
            </a>
            <a
              href="/about"
              className="text-sm font-semibold leading-6 text-black-900"
            >
              About us
            </a>
            <a
              href="/contact"
              className="text-sm font-semibold leading-6 text-black-900"
            >
              Contact
            </a>
            <a className="dropdown">
              <a
                className="dropbtn"
                style={{ color: "black", fontWeight: "550" }}
              >
                Library
                <i className="fa fa-caret-down"></i>
              </a>
              <div className="dropdown-content">
                <a href="/library">Book store</a>
                <a href="/meeting-room">Meeting room</a>
                <a href="/book-table">My books</a>
              </div>
            </a>
          </Popover.Group>
          <div className="hidden lg:flex lg:flex-1 lg:justify-end">
            {context?.user === undefined ? (
              <a
                href="/"
                className="text-sm font-semibold leading-6 text-black-900"
              >
                Log in <span aria-hidden="true">&rarr;</span>
              </a>
            ) : (
              <a
                onClick={() => context.setUser(undefined)}
                href="/"
                className="text-sm font-semibold leading-6 text-black-900"
              >
                Log out <span aria-hidden="true">&rarr;</span>
              </a>
              // access the username here
            )}

这是我正在包装的应用程序

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import { BrowserRouter } from "react-router-dom";
import Login from "./pages/Login.tsx";
import Signup from "./pages/Signup.tsx";
import { Routes, Route } from "react-router-dom";
import Home from "./pages/Home.tsx";
import socket from "./Socket.tsx";
import { NotificationProvider } from "./context/NotificationProvider.tsx";
import Navbar from "./components/Navbar.tsx";
import { AuthProvider } from "./context/AuthProvider.tsx";

// import './styles/About.css'
// import './styles/Library.css'
// import './styles/Home.css'
// import './styles/myBooks.css'
//meeting-room
import About from "./pages/About.tsx";
import Library from "./pages/Library.tsx";
import BookTable from "./components/BookTable.tsx";
import MeetingRoomsPage from "./pages/BookingRoomsPage.tsx";
import Contact from "./pages/Contact.tsx";
import ReserveRooms from "./pages/ReservedRooms.tsx";

ReactDOM.createRoot(document.getElementById("root")!).render(
  
  <BrowserRouter>
    
      <NotificationProvider />
      <AuthProvider>
      <Routes>
        <Route path="/" element={<Login></Login>}></Route>
        <Route path="/signup" element={<Signup></Signup>}></Route>
        <Route path="/home" element={<Home></Home>}></Route>
        <Route path="/about" element={<About></About>}></Route>
        <Route path="/library" element={<Library></Library>}></Route>
        <Route path="/book-table" element={<BookTable></BookTable>}></Route>
        <Route path="/meeting-room" element={<MeetingRoomsPage></MeetingRoomsPage>}></Route>
        <Route path="/reserver-rooms" element={<ReserveRooms></ReserveRooms>}></Route>
        <Route path="/contact" element={<Contact></Contact>}></Route>
      </Routes>
      </AuthProvider>
 
   
  </BrowserRouter>
  
);

我只是尝试在其他页面中控制台登录,其中登录选项返回,我发现导航到其他页面时上下文变得未定义。它应该使用用户信息进行定义,以便登录选项永远不会消失,除非我注销

reactjs undefined react-context
1个回答
0
投票

问题在于您的 AuthProvider 包裹在您的路由中,但包含显示登录/注销链接的逻辑的导航栏组件在 AuthProvider 外部呈现。在您的文件中,您具有以下结构:

ReactDOM.createRoot(document.getElementById("root")!).render(
    <BrowserRouter>
        <NotificationProvider />
        <AuthProvider> {/* AuthProvider wraps around Routes */}
            <Routes>
                {/* Routes go here */}
            </Routes>
        </AuthProvider>
    </BrowserRouter>
);

由于导航栏是在 AuthProvider 之外渲染的,因此它无法访问 AuthContext,因此上下文变得未定义。

您需要将导航栏组件移至 AuthProvider 内。

ReactDOM.createRoot(document.getElementById("root")!).render(
    <BrowserRouter>
        <NotificationProvider />
        <AuthProvider> {/* AuthProvider wraps around everything */}
            <Navbar /> {/* Render Navbar inside AuthProvider */}
            <Routes>
                {/* Routes go here */}
            </Routes>
        </AuthProvider>
    </BrowserRouter>
);

通过在 AuthProvider 内渲染 Navbar 组件,它将可以访问 AuthContext,并应根据用户的身份验证状态正确显示登录/注销链接。

© www.soinside.com 2019 - 2024. All rights reserved.