App.js 在我登录时不呈现 AuthContext

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

我正在开发一个系统,该系统具有登录功能并且运行成功。该登录过程需要用户名和角色。当我在 Login.jsx 上检查它时,一切正常,我可以正确地看到角色和用户名。问题是我有一个侧边栏组件,我想在成功登录后而不是登录之前渲染该侧边栏。当我检查 App.js 中的用户名和角色时,它们是未定义的。为什么会这样。顺便说一句,如果我添加没有条件渲染的侧边栏,我可以看到 3 个用户的 3 个不同的侧边栏,我可以使用角色来设置它。我相信会发生这种情况是因为登录和侧边栏位于同一层次结构上。请帮助我

AuthProvider.js:

import { createContext, useState } from "react";

const AuthContext = createContext({});

export const AuthProvider = ({ children }) => {
    const [auth, setAuth] = useState({
        username: null,
        password: null,
        role: null,
        accessToken: null,
    });

    const login = ({ username, password, role, accessToken }) => {
        setAuth({
            username,
            password,
            role,
            accessToken,
        })
    }

    const logout = () => {
        setAuth({
            username: null,
            password: null,
            role: null,
            accessToken: null,
        })
    }

    return (
        <AuthContext.Provider value={{ auth, setAuth, login, logout }}>
            {children}
        </AuthContext.Provider>
    )
}

export default AuthContext;

登录.jsx:

import React, { useEffect, useState, useRef } from 'react';
import { useNavigate, Link, useLocation } from 'react-router-dom'; // Import useNavigate
import useAuth from './hooks/useAuth';

// Img
import LoginBg from "../assets/img/upg-bg.jpg";

const Login = (props) => {
    const { setAuth, login } = useAuth();

    const navigate = useNavigate();
    const location = useLocation();
    const from = location.state?.from?.pathname || "/";

    const userRef = useRef();
    const errRef = useRef();

    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");
    const [errMsg, setErrMsg] = useState("");

    // const { login } = useAuth();

    const handleLogin = async (e) => {
        e.preventDefault();
        try {
            const response = await fetch(`some url in here`, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({ username, password }),
            })
            const data = await response.json();
            const role = data.role[0].roleName;
            const accessToken = data.token;
            console.log("role from login", role)
            // login(data.token, data.role[0].roleName);
            // setAuth({ username, password, role, accesToken })
            login({
                username: username,
                password: password,
                role: role,
                accessToken: accessToken,
            })
            setUsername("");
            setPassword("");
            navigate("/", { replace: true });

        } catch (error) {
            if (error.response?.status === 400) {
                setErrMsg("Yanlış kullanıcı adı ya da şifre!");
            } else if (error.response?.status === 401) {
                setErrMsg("Yetkiniz Yok!");
            } else {
                setErrMsg("Giriş başarısız!");
            }
            errRef.current?.focus();
        }
    }

    // To login on press Enter
    const handleKeyPress = e => {
        if (e.keyCode === 13) {
            handleLogin();
        }
    }

    useEffect(() => {
        userRef.current?.focus();
    }, [])

    useEffect(() => {
        setErrMsg("");
    }, [username, password])

    useEffect(() => {
        console.log("user context updated", login)
    }, [login]) 

    return (
        <div onKeyDown={handleKeyPress} id='login-page' className=' absolute z-30 w-screen h-screen'>
         // some divs etc...
        </div>
    )
}

export default Login

App.js:

import React, { useState, useEffect } from "react";
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { AuthProvider } from "./components/auth/AuthProvider";

import Login from "./components/Login";
import Sidebar from "./components/Sidebar";


function App() {
  const { auth, login } = useAuth();
  console.log("role from app", auth?.role)
  console.log("login", login.role)

  return (
    <AuthProvider>
      <div className="App">
        <Routes>
           <Route path="/login" element={<Login />} />
         </Routes>

         <div className="flex">
           {auth?.role === 'admin' && <Sidebar />}
         </div>
      </div>
    </AuthProvider>
  )
}

侧边栏.jsx:

import React from 'react'
import { Link } from 'react-router-dom';
import useAuth from './hooks/useAuth';

import { MdTableView, MdOutlineLogout } from 'react-icons/md';
import { AiOutlineQuestionCircle, AiOutlinePlusCircle } from 'react-icons/ai';
import { TbCircleLetterC } from 'react-icons/tb';

const Sidebar = (props) => {
    const { auth } = useAuth();

    const logOut = () => {
        // props.setIsLoggedIn(false);
    }

    const sidebarSelect = (id) => {
        const link = document.getElementById(id);

        // Deselect link if there is any
        const previouslySelectedLinks = document.querySelectorAll(".selected");
        previouslySelectedLinks.forEach((div) => {
            div.classList?.remove("selected", "bg-zinc-600");
            div.classList?.add("hover:bg-zinc-600");
        });

        // Select new link
        link.classList?.add("bg-zinc-600", "selected");
        link.classList?.remove("hover:bg-zinc-600");
    }

    return (
        <div id="sidebar" className='flex-none bg-gradient-to-b from-zinc-700 to-zinc-900 fixed w-full top-0 bottom-0 max-w-[16rem] -ms-[16.5rem] md:ms-3 my-3 rounded-lg text-white duration-300 z-10'>
            <div id="sidebar-header" className='py-6 text-center'>
                {/* <Link to="/">
                    </Link> */}
                <h1 id='sidebar-title' className='font-bold'>İstanbul Medeniyet Universitesi</h1>
            </div>

            <hr className='mx-4' />

            <div className='py-6 mx-4'>
                <ul className='flex flex-col'>

                    {auth?.role === 'admin' && (<Link id='0' onClick={() => sidebarSelect(0)} to="/admin-dashboard" className='flex items-center gap-2 hover:bg-zinc-600 p-2 rounded-lg duration-300'> <MdTableView size={25} /> Admin Paneli</Link>)}


                    <Link id='1' onClick={() => sidebarSelect(1)} to="/" className='flex items-center gap-2 hover:bg-zinc-600 p-2 rounded-lg duration-300 mt-2 selected bg-zinc-600'> <AiOutlineQuestionCircle size={25} /> Birim Sorular</Link>

                    {(auth.role === 'admin' || auth?.role === 'upg') && (<Link id='2' onClick={() => sidebarSelect(2)} to="/upg-soru-ekle" className='flex items-center gap-2 hover:bg-zinc-600 p-2 rounded-lg duration-300 mt-2'>
                        <div className='relative'>
                            <AiOutlineQuestionCircle size={25} />

                            <AiOutlinePlusCircle className='absolute top-3 -right-1 rounded-full bg-zinc-700 ' size={15} />
                        </div>
                        UPG Soru Ekle</Link>)}

                    {(auth.role === 'admin' || auth?.role === 'upg') && (<Link id='3' onClick={() => sidebarSelect(3)} to="/upg-cevaplar" className='flex items-center gap-2 hover:bg-zinc-600 p-2 rounded-lg duration-300 mt-2'> <TbCircleLetterC size={25} />UPG Cevaplar</Link>)}

                    {(auth.role === 'admin' || auth?.role === 'upg') && (<Link id='4' onClick={() => sidebarSelect(4)} to="/upg-cevap-basligi-ekle" className='flex items-center gap-2 hover:bg-zinc-600 p-2 rounded-lg duration-300 mt-2'>
                        <div className='relative'>
                            <TbCircleLetterC size={25} />

                            <AiOutlinePlusCircle className='absolute top-3 -right-1 rounded-full bg-zinc-700 ' size={15} />
                        </div>
                        UPG Cevap Başlığı Ekle</Link>)}

                    {/* <Link id='5' onClick={() => { logOut(); }} to="/" className='flex items-center gap-2 hover:bg-zinc-600 p-2 rounded-lg duration-300 mt-2'> <MdOutlineLogout size={25} /> Çıkış Yap</Link> */}
                    <Logout />
                </ul>
            </div>
        </div>
    )
}

我尝试在立即登录后获取用户名和角色

reactjs react-hooks react-router react-context createcontext
2个回答
0
投票

看起来

useAuth
钩子正在内部调用
useContext(AuthContext)
。如果这是真的,则意味着您正在尝试在 App.js 中获取
AuthContext
之外的
AuthProvider
。结果,您获得上下文的默认值,它是一个空对象
{}
,并获得
undefined
其属性。要解决这个问题,我觉得你应该想办法在
useAuth
下调用
AuthProvider
。下面是我认为您的代码应该是的简单版本。

function App() {
  return (
    <AuthProvider>
      <Sidebar />
    </AuthProvider>
  );
}

const Sidebar = () => {
  const { auth } = useAuth();

  if (auth?.role !== "admin") {
    return null;
  }

  // ...
};


0
投票

我在AuthProvider中添加了侧边栏,这解决了我的问题,登录系统后我可以看到侧边栏

import { createContext, useState } from "react";
import Sidebar from "../Sidebar";

const AuthContext = createContext({});

export const AuthProvider = ({ children }) => {
    const [auth, setAuth] = useState({
        username: null,
        password: null,
        role: null,
        accessToken: null,
    });

    const login = ({ username, password, role, accessToken }) => {
        setAuth({
            username,
            password,
            role,
            accessToken,
        })
    }

    const logout = () => {
        setAuth({
            username: null,
            password: null,
            role: null,
            accessToken: null,
        })
    }

    return (
        <AuthContext.Provider value={{ auth, setAuth, login, logout }}>
            {auth.username && <Sidebar/>}
            {children}
        </AuthContext.Provider>
    )
}

export default AuthContext;
© www.soinside.com 2019 - 2024. All rights reserved.