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

React项目中Material UI弹窗无法在当前页面打开的问题求助

解决Material UI Dialog在当前页面弹窗而非跳转路由的问题

这个问题的核心是你之前把Dialog做成了独立路由,导致点击后直接跳转页面。我们可以通过状态共享的方式,让Dialog在当前页面(Home/About)之上弹出,而不是跳转到新路由。下面是具体的修改步骤和代码:

1. 把Dialog的控制状态提升到App组件

App是SideMenu、Home、About的父组件,我们在这里维护Dialog的显示状态,这样所有子组件都能共享这个状态来控制弹窗:

// App.js
import React, { useState } from "react";
import "./styles.css";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Home from "./home";
import About from "./about";
import Dialog from "./dialog";
import SideMenu from "./sidemu";

export default function App() {
  // 新增:控制Dialog显示的状态
  const [dialogOpen, setDialogOpen] = useState(false);

  // 打开Dialog的方法
  const openDialog = () => {
    setDialogOpen(true);
  };

  // 关闭Dialog的方法
  const closeDialog = () => {
    setDialogOpen(false);
  };

  return (
    <div className="App">
      <BrowserRouter>
        {/* 把打开Dialog的方法传给SideMenu */}
        <SideMenu openDialog={openDialog} />
        <Switch>
          <Route exact path="/" component={Home} />
          <Route exact path="/about" component={About} />
        </Switch>
        {/* 在路由外层渲染Dialog,传递控制属性 */}
        <Dialog open={dialogOpen} onClose={closeDialog} />
      </BrowserRouter>
    </div>
  );
}

2. 修改SideMenu,替换Link为点击事件触发弹窗

原来的Link会触发路由跳转,我们把它改成普通的列表项,点击时调用父组件传过来的openDialog方法,同时自动关闭侧边栏:

// SideMenu.js
import React from 'react';
import './styles.css';
import { Link } from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import { List, ListItemIcon, ListItem, ListItemText } from '@material-ui/core';
import MenuRoundedIcon from '@material-ui/icons/MenuRounded';
import HomeRoundedIcon from '@material-ui/icons/HomeRounded';
import MenuBookRoundedIcon from '@material-ui/icons/MenuBookRounded';

const useStyles = makeStyles({
  list: {
    width: 250,
  },
  fullList: {
    width: 'auto',
  },
});

// 新增:接收父组件传来的openDialog方法
export default function TemporaryDrawer({ openDialog }) {
  const classes = useStyles();
  const [state, setState] = React.useState({
    top: false,
    left: false,
    bottom: false,
    right: false,
  });

  const toggleDrawer = (side, open) => event => {
    if (event.type === 'keydown' && (event.key === 'Tab' || event.key === 'Shift')) {
      return;
    }
    setState({ ...state, [side]: open });
  };

  const sideList = side => (
    <div className={classes.list} role="presentation" onClick={toggleDrawer(side, false)} onKeyDown={toggleDrawer(side, false)} >
      <List>
        <Link className="right-menu-data" to="/">
          <ListItem button>
            <ListItemIcon>
              <HomeRoundedIcon />
            </ListItemIcon>
            <ListItemText>Home</ListItemText>
          </ListItem>
        </Link>
        <Link className="right-menu-data" to="/about">
          <ListItem button>
            <ListItemIcon>
              <MenuBookRoundedIcon />
            </ListItemIcon>
            <ListItemText>About us</ListItemText>
          </ListItem>
        </Link>
        {/* 修改:去掉Link,改成点击触发弹窗+关闭侧边栏 */}
        <ListItem button onClick={() => {
          openDialog(); // 打开注册弹窗
          toggleDrawer(side, false)(); // 关闭侧边栏
        }}>
          <ListItemIcon>
            <MenuBookRoundedIcon />
          </ListItemIcon>
          <ListItemText>User Registration</ListItemText>
        </ListItem>
      </List>
    </div>
  );

  return (
    <div>
      <MenuRoundedIcon className="careerpedia-menu-bars" onClick={toggleDrawer('right', true)} />
      <Drawer anchor="right" open={state.right} onClose={toggleDrawer('right', false)}>
        {sideList('right')}
      </Drawer>
    </div>
  );
}

3. 调整Dialog组件,改成受控组件

原来的Dialog自己维护显示状态,现在改成由父组件传递open和onClose属性来控制,让它成为一个纯展示的组件:

// Dialog.js
import React from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';

// 新增:接收父组件传来的open和onClose属性
export default function AlertDialog({ open, onClose }) {
  return (
    <div>
      <Dialog 
        open={open} 
        onClose={onClose} 
        aria-labelledby="alert-dialog-title" 
        aria-describedby="alert-dialog-description"
      >
        <DialogTitle id="alert-dialog-title">{"User Registration"}</DialogTitle>
        <DialogContent>
          <DialogContentText id="alert-dialog-description">
            这里可以放置你的用户注册表单内容
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button onClick={onClose} color="primary">
            Cancel
          </Button>
          <Button onClick={onClose} color="primary" autoFocus>
            Register
          </Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}

为什么这样改?

  • 状态提升到App后,不管当前是Home还是About页面,都能共享Dialog的显示状态,确保弹窗在当前页面之上弹出
  • 移除了/dialog路由,避免跳转页面,保持当前页面的路由状态不变
  • Dialog变成受控组件,完全由父组件控制显示隐藏,逻辑更清晰,也更容易扩展后续功能

这样修改后,点击侧边栏的“用户注册”就会在当前页面弹出Dialog,而不会跳转到新页面了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 22:37:34