按钮点击无法切换Menu组件状态(跨文件组件同步问题)
我的代码文件
RootLayout文件
import Menu from "./Menu"; import ButtonMenu from "./ButtonMenu"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body className="grid h-screen grid-cols-[repeat(4,min-content)] overflow-x-scroll"> <Menu /> <Pane1 /> <Pane2 /> <Pane3 /> <div className="w-[100vw]"> <ButtonMenu /> <main>{children}</main> </div> </body> </html> ); }
Menu文件
"use client"; import { useState } from "react"; export default function Menu() { const [open, setOpen] = useState(true); return ( <div className={` overflow-x-hidden overflow-y-scroll ${ open ? "w-[5vw]" : "w-[20vw]" }`} > <nav><ul><li></li></ul></nav> </div> ); }
ButtonMenu文件
"use client"; import { useState } from "react"; export default function OpenMenu() { const [open, setOpen] = useState(true); return ( <div> <button type="button" onClick={() => setOpen(!open)}> ... </button> </div> ); }
问题描述
在ButtonMenu文件中的button触发onClick事件时,Menu组件并未展开/收起,无任何响应。Menu与ButtonMenu是两个独立文件的组件,均被引入到RootLayout中,为何点击按钮无法控制Menu的状态?
原因分析
Menu和ButtonMenu各自维护了完全独立的open状态,这两个状态没有任何关联。点击ButtonMenu里的按钮只会修改它自己内部的open值,根本影响不到Menu组件里的状态,所以Menu不会有任何变化。
解决方案
把状态提升到它们的共同父组件RootLayout中,通过props传递状态和修改状态的方法:
1. 修改RootLayout,维护共享状态
"use client"; import Menu from "./Menu"; import ButtonMenu from "./ButtonMenu"; import { useState } from "react"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { const [menuOpen, setMenuOpen] = useState(true); return ( <html lang="en"> <body className="grid h-screen grid-cols-[repeat(4,min-content)] overflow-x-scroll"> <Menu open={menuOpen} /> <Pane1 /> <Pane2 /> <Pane3 /> <div className="w-[100vw]"> <ButtonMenu onToggleMenu={() => setMenuOpen(!menuOpen)} /> <main>{children}</main> </div> </body> </html> ); }
2. 修改Menu组件,接收父组件传递的状态
"use client"; export default function Menu({ open }: { open: boolean }) { return ( <div className={` overflow-x-hidden overflow-y-scroll ${ open ? "w-[5vw]" : "w-[20vw]" }`} > <nav><ul><li></li></ul></nav> </div> ); }
3. 修改ButtonMenu组件,接收父组件的切换方法
"use client"; export default function ButtonMenu({ onToggleMenu }: { onToggleMenu: () => void }) { return ( <div> <button type="button" onClick={onToggleMenu}> 切换菜单 </button> </div> ); }
修改后,点击按钮就会调用父组件的setMenuOpen方法修改共享状态,Menu组件接收到更新后的open值,就会自动切换宽度,实现展开/收起效果。
内容的提问来源于stack exchange,提问作者Boq7
相关产品推荐
相关产品推荐

