React非父子组件中,能否通过一个组件的onClick事件触发另一组件功能?
非父子关系的React组件完全可以实现跨组件的状态同步和方法调用,你的场景属于同级组件通信,最简单的实现方案是使用React官方推荐的「状态提升」逻辑,将共享的抽屉显隐状态放到两个组件的共同父组件App中维护,再通过props传递给需要的组件即可,无需引入额外的状态管理工具。
注意事项
你当前自定义的抽屉组件名和Material UI自带的Drawer组件重名,会引发引用冲突,首先将自定义抽屉组件重命名为AppDrawer避免冲突。
分步实现代码
1. 修改独立抽屉组件 AppDrawer.js
import Drawer from '@mui/material/Drawer'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import InboxIcon from '@mui/icons-material/Inbox'; import MailIcon from '@mui/icons-material/Mail'; // 接收父组件传递的显隐状态和关闭方法 export const AppDrawer = ({ open, onClose }) => { return ( <div> <Drawer variant="temporary" anchor="left" open={open} onClose={onClose} > <div /> <List> {["Inbox", "Starred", "Send email", "Drafts"].map((text, index) => ( <ListItem button key={text}> <ListItemIcon> {index % 2 === 0 ? <InboxIcon /> : <MailIcon />} </ListItemIcon> <ListItemText primary={text} /> </ListItem> ))} </List> </Drawer> </div> ); };
2. 修改 Header.js
移除内部维护的open状态和toggleDrawer逻辑,改为接收父组件传递的切换方法:
import IconButton from '@mui/material/IconButton'; import MenuIcon from '@mui/icons-material/Menu'; // 接收父组件传递的抽屉切换方法 export const Header = ({ toggleDrawer }) => { return ( <header role="banner" className="header header-beta header-mobile"> <div className="header__content" > <div className="header__nav"> <div style={{margin: 'auto', paddingRight: '4px'}}> <IconButton color="default" aria-label="open drawer" edge="start" onClick={toggleDrawer} className="round-button round-button--minimal round-button--icon js-trigger-drawer-left" > <span className="round-button__content"> <i className="icon icon--sm"> <MenuIcon /> </i> </span> </IconButton> </div> </div> </div> </header> ); };
3. 修改 App.js
将共享状态和切换逻辑提升到父组件,同时引入两个子组件并传递对应props:
import { useState } from 'react'; import { Header } from './Header'; import { AppDrawer } from './AppDrawer'; export default function App() { // 提升到父组件维护的抽屉显隐状态 const [open, setOpen] = useState(false); const toggleDrawer = event => { if ( event.type === "keydown" && (event.key === "Tab" || event.key === "Shift") ) { return; } setOpen(!open); }; return ( <> <Header toggleDrawer={toggleDrawer} /> <AppDrawer open={open} onClose={toggleDrawer} /> </> ); }
拓展说明
如果后续项目复杂度提升,存在大量跨层级组件需要共享状态,你也可以选择React Context、Redux、Zustand等状态管理方案实现组件通信,但当前场景下状态提升是最简单且无额外依赖成本的实现方式。
内容的提问来源于stack exchange,提问作者Hania Salman
相关产品推荐
相关产品推荐

