You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在用户未登录时隐藏全局侧边栏与顶部导航,仅显示登录页

问题根源

你的App组件里的token是初始化时从localStorage取的一次性值,后续即便localStorage中的token被移除,App组件不会自动重新渲染,所以Sidebar会一直显示,直到刷新页面触发组件重新初始化。而Topbar能正常隐藏,是因为它每次渲染都会重新检查token(推测你在Topbar内部做了localStorage.getItem("token")的操作),路由跳转到/login后Topbar重新渲染,自然就隐藏了。

解决办法

方法一:让App组件监听路由变化,同步token状态

用React状态存储token,每次路由切换时重新从localStorage获取最新值,触发App组件重新渲染,从而控制Sidebar的显示:

import { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';

const App=()=> {
    // 初始化时读取token存入状态
    const [token, setToken] = useState(localStorage.getItem("token"));
    const location = useLocation();

    useEffect(() => {
        // 路由变化时重新获取token并更新状态
        const currentToken = localStorage.getItem("token");
        setToken(currentToken);
    }, [location.pathname]);

    return (
        <div className="App">
            {/* 仅当token存在时渲染Sidebar */}
            {token && <Sidebar/>}
            <Box sx={{
                display: 'flex',
                flexDirection:'column',
                width: '100%',
            }}>
                <Topbar/>
                <main className="content">
                    <MainRoutes/>
                </main>
            </Box>
        </div>
    ); 
}

方法二:监听localStorage变化,支持跨标签页同步

如果需要跨标签页同步登录状态,可以添加storage事件监听,其他标签页操作token时,当前页面也能同步更新状态:

import { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';

const App=()=> {
    const [token, setToken] = useState(localStorage.getItem("token"));
    const location = useLocation();

    // 监听路由变化,同步token状态
    useEffect(() => {
        setToken(localStorage.getItem("token"));
    }, [location.pathname]);

    // 监听localStorage的storage事件,跨标签页同步状态
    useEffect(() => {
        const updateToken = (e) => {
            if (e.key === "token") {
                setToken(localStorage.getItem("token"));
            }
        };
        window.addEventListener('storage', updateToken);
        // 组件卸载时移除监听
        return () => window.removeEventListener('storage', updateToken);
    }, []);

    return (
        <div className="App">
            {token && <Sidebar/>}
            <Box sx={{
                display: 'flex',
                flexDirection:'column',
                width: '100%',
            }}>
                <Topbar/>
                <main className="content">
                    <MainRoutes/>
                </main>
            </Box>
        </div>
    ); 
}

方法三:全局状态管理(更优雅,适合中大型项目)

用React Context封装登录状态,让所有组件共享token,登出时直接更新全局状态,无需依赖localStorage监听:

1. 创建AuthContext

// AuthContext.js
import { createContext, useState, useContext, useEffect } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
    const [token, setToken] = useState(localStorage.getItem("token"));

    // 全局登出方法
    const logout = () => {
        localStorage.removeItem("token");
        setToken(null);
    };

    // 全局登录方法
    const login = (newToken) => {
        localStorage.setItem("token", newToken);
        setToken(newToken);
    };

    // 监听storage变化,同步跨标签页状态
    useEffect(() => {
        const handleStorageChange = (e) => {
            if (e.key === "token") {
                setToken(localStorage.getItem("token"));
            }
        };
        window.addEventListener('storage', handleStorageChange);
        return () => window.removeEventListener('storage', handleStorageChange);
    }, []);

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

// 自定义hooks,简化组件调用
export const useAuth = () => useContext(AuthContext);

2. 在App组件中使用

import { useAuth } from './AuthContext';

const App=()=> {
    const { token } = useAuth();

    return (
        <div className="App">
            {token && <Sidebar/>}
            <Box sx={{
                display: 'flex',
                flexDirection:'column',
                width: '100%',
            }}>
                <Topbar/>
                <main className="content">
                    <MainRoutes/>
                </main>
            </Box>
        </div>
    ); 
}

3. 修改Topbar的登出逻辑

import { useAuth } from './AuthContext';
import { useNavigate } from 'react-router-dom';

const Topbar = () => {
    const { token, logout } = useAuth();
    const navigate = useNavigate();

    const handleLogout = () => {
        logout();
        navigate('/login');
    };

    return (token &&
        <Box sx={{
            background: `${colors.yellow[101]}`,
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            height: 50,
        }}>
            <Typography variant="h5">X2XBET Account Management</Typography>
              <Box>
                <IconButton onClick={handleLogout}>
                   <LogoutRoundedIcon />
                </IconButton>
            </Box>
        </Box>
    )
}

内容的提问来源于stack exchange,提问作者Inno Namsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 11:50:22