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

如何在React.js中使用Context API管理全局状态并修复导航栏交互问题

问题原因与修复方案

1. 先修复Layout组件的Context作用域问题

你的ToggleProvider没有包裹实际渲染导航栏的children节点,导致Navbar根本拿不到ToggleContext的正确值,修改Layout.js代码:

function Layout ({startingTheme, startingToggle, children}) { 
    return (
        <>
        <ThemeProvider startingTheme={startingTheme} >
            <ToggleProvider startingToggle={startingToggle}>
                {/* 把children放到ToggleProvider内部,这样Navbar才能拿到切换状态 */}
                <LayoutNoToggleProvider>
                    <LayoutNoThemeProvider >{children}</LayoutNoThemeProvider>
                </LayoutNoToggleProvider> 
            </ToggleProvider>
        </ThemeProvider>        
        </>
    );
}

同时修正LayoutNoToggleProvider里的类名判断逻辑,和useToggle的返回值类型对齐:

function LayoutNoToggleProvider ({children}) {
    const  { toggle } = useContext(ToggleContext);
    return (
        // 你的toggle是字符串类型,判断是否等于"show"即可
        <div className={            
        toggle !== "show" ? "navbar navbar-collapsed" : "navbar navbar-collapse show"
        }> 
        {children}     
        </div>
    )
}

2. 修复Navbar的Context取值和点击事件

首先ToggleContext返回的是包含toggle状态和setToggle方法的对象,不能直接赋值给toggle变量,其次点击事件的逻辑完全错误,没有调用状态更新方法,修改Navbar.js代码:

// 解构出ToggleContext里的状态和方法
const { toggle, setToggle } = useContext(ToggleContext);
// 主题Context也要解构,不然你拿到的也是整个对象,判断theme会出错
const { theme } = useContext(ThemeContext);

然后修改按钮的onClick事件:

<button
    onClick={ () => {
        // 切换状态:当前是show就设为空,否则设为show
        setToggle(toggle === "show" ? "" : "show")
        console.log("clicked")
    }}
    className="navbar-toggler collapsed" 
    type="button" 
    // 去掉bootstrap的data-bs-toggle属性,你已经用React控制状态了,不要让原生bootstrap和React冲突
    // data-bs-toggle="collapsed" 
    data-bs-target="#navbarResponsive" 
    aria-controls="navbarResponsive" 
    aria-expanded={toggle === "show"}
    aria-label="Toggle navigation"
>

另外你Nav里重复写了两遍菜单DOM,完全没必要,直接根据toggle值动态改类名就可以,还可以补充菜单项点击关闭菜单的逻辑:

<div 
    className={`navbar-collapse mt-2 ${toggle === "show" ? "show" : "collapsed"}`}
    id="navbarResponsive"
>
    <ul className="navbar-nav text-uppercase ms-auto py-4 py-lg-0">
        {navbarData.map((link,idx) => {
            return (
                <li key={link.id}>
                    <Link  href={`/${link.ref}`} className="nav-item" data-index={idx} passHref>
                    <a className="nav-link" onClick={() => {
                        // 点击菜单项自动关闭菜单
                        setToggle("")
                        console.log("菜单项被点击")
                    }}>
                    {link.title}
                    </a>
                    </Link>
                </li>
            );
        })}
    </ul>
</div>

3. 可选优化useToggle逻辑

如果不需要用字符串标识状态,直接用布尔值会更简单,修改useToggle.js:

import { useState } from "react";

function useToggle (startingToggle = false) {
    // 初始值转布尔值,避免传入字符串导致判断出错
    const [toggle, setToggle] = useState(!!startingToggle);
    const toggleMenu = () => setToggle(prev => !prev)
    return {
        toggle,
        setToggle,
        toggleMenu
    }
}
export default useToggle;

改完之后按钮点击事件可以直接调用toggleMenu(),不需要手动判断状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 06:45:04