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

基于全局状态布尔值切换导航栏出现白屏问题求助

React Context 实现全局状态导致页面白屏问题排查与修复

我正在使用React Context API实现全局状态,希望根据用户登录状态切换导航栏,但页面出现白屏,以下是相关代码及问题修复方案:

AppContext.js

import React from "react";
// ./components/AppContext.js
const AppContext = React.createContext();

export default AppContext;

Index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import { CookiesProvider } from 'react-cookie';
import App from "./App";
import AppContext from "./components/AppContext";
// index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <React.StrictMode>
        <CookiesProvider>
            <App/>
        </CookiesProvider>
    </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: 
reportWebVitals();

App.js(存在问题版本)

import React, {useState} from 'react';
import './App.css';
import Home from './Home';
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import User from "./User";

import NavBarSI from "./components/NavBarSignedIn";
import NavBarGL from "./components/NavBarGeneral";
import AppContext from "./components/AppContext";

//App.js
const App = () => {
    const userSettings = {
        setting2name: setting2value,
        setSetting2value
    };
    const [setting2value, setSetting2value] = useState(false);


    const navbar = setting2value ?
        <NavBarSI/> : <NavBarGL/>

    return (

        <Router>
            <AppContext.Provider value={userSettings}>
                {navbar}
                <NavBarSI/>
                <div>
                    <Routes>
                        <Route exact path="/" element={<Home/>}/>
                        <Route exact path="/user" element={<User/>}/>
                    </Routes>
                </div>
            </AppContext.Provider>
        </Router>

    );
}

export default App;

Home.js

import React, {useContext, useEffect, useState} from 'react';
import './App.css';
import { Button, Container } from 'reactstrap';
import { useCookies } from 'react-cookie';
import AppContext from "./components/AppContext";


// Home.js
const Home = () => {

    const myContext = useContext(AppContext);
    const [authenticated, setAuthenticated] = useState("authenticated");
    const [loading, setLoading] = useState(false);
    const [user, setUser] = useState(undefined);
    const [cookies] = useCookies(['XSRF-TOKEN']);



    useEffect(() => {
        setLoading(true);
            fetch('/user', { credentials: 'include' })
            .then(response => response.text())
            .then(body => {
                if (body === '') {
                    setAuthenticated(false);


                } else {
                    setUser(JSON.parse(body));
                    setAuthenticated(true);
                    myContext.setSetting2value(true);

                }
                setLoading(false);
            });
    }, [setAuthenticated, setLoading, setUser])

    const login = () => {
        let port = (window.location.port ? ':' + window.location.port : '');
        if (port === ':3000') {
            port = ':8080';
        }
        window.location.href = `//${window.location.hostname}${port}/private`;
    }

    const logout = () => {
        fetch('/user/logout', {
            method: 'POST', credentials: 'include',
            headers: { 'X-XSRF-TOKEN': cookies['XSRF-TOKEN'] }
        })
            .then(res => res.json())
            .then(response => {
                window.location.href = `${response.logoutUrl}&returnTo=${window.location.origin}`;
            });
    }

    const message = user ?
        <h2>Welcome, {user.name}!</h2> :
        <p>Please log in to manage your JUG Tour.</p>;

    const button = authenticated ?
        <div>
            <br/>
            <Button color="link" onClick={logout}>Logout</Button>
        </div> :
        <Button color="primary" onClick={login}>Login</Button>;;



    if (loading) {
        return <p>Loading...</p>;
    }


    return (
        <div>
            <Container fluid>
                {message}
                {button}
            </Container>
        </div>
    );
}


export default Home;

问题分析与修复

1. 变量声明顺序错误(白屏直接原因)

在App.js中,userSettings对象的定义在useState声明之前,导致setting2value和setSetting2value未被声明就被引用,触发ReferenceError,直接导致页面白屏。

修复方法:调整声明顺序,先定义useState再创建context值对象:

const App = () => {
    // 先声明state
    const [setting2value, setSetting2value] = useState(false);
    // 再创建context值
    const userSettings = {
        setting2name: setting2value,
        setSetting2value
    };

    const navbar = setting2value ? <NavBarSI/> : <NavBarGL/>

    return (
        <Router>
            <AppContext.Provider value={userSettings}>
                {navbar}
                {/* 移除重复渲染的<NavBarSI/> */}
                <div>
                    <Routes>
                        <Route exact path="/" element={<Home/>}/>
                        <Route exact path="/user" element={<User/>}/>
                    </Routes>
                </div>
            </AppContext.Provider>
        </Router>
    );
}

2. 导航栏重复渲染

原App.js中同时渲染了{navbar}和<NavBarSI/>,会导致页面出现两个导航栏,需移除重复的<NavBarSI/>。

3. Home.js中的潜在问题

  • authenticated初始值为字符串"authenticated",应改为布尔值false,避免初始状态判断逻辑错误:
    const [authenticated, setAuthenticated] = useState(false);
    
  • useEffect依赖数组缺少myContext.setSetting2value,会触发React警告,需补充:
    useEffect(() => {
        // ...原有逻辑
    }, [setAuthenticated, setLoading, setUser, myContext.setSetting2value])
    

修复后验证

完成上述修改后,页面将正常渲染,登录状态变更时会自动切换导航栏组件,同时消除控制台错误与警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:46:00