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

React中路由跳转至其他页面时如何自动关闭Modal弹窗

问题描述

我在项目中使用react-router-dom与Material UI Modal组件,希望实现用户导航跳转至其他页面时自动隐藏弹窗的效果。

以下是我的App组件代码:

const App = () => (
  <BrowserRouter>
    <ModalHandlersProvider>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<Home />} />
        </Route>
      </Routes>
    </ModalHandlersProvider>
  </BrowserRouter>
);

export default App;

我在ModalHandlersProvider组件中渲染CustomModal,通过Context API传递弹窗相关操作方法,相关代码如下:

const ModalHandlersContext = React.createContext(initialState);
export const useModalHandlersContext = () => useContext(ModalHandlersContext);

const ModalHandlersProvider = ({ children }) => {
  const [modal, setModal] = useState(initialState);
  const handlers = {
    openModal: setModal,
    closeModal: () => setModal(initialState),
  };

  return (
    <ModalHandlersContext.Provider value={handlers}>
      {children}
      <CustomModal
        open={modal.open}
        onClose={handlers.closeModal}
        content={modal.content}
      ></CustomModal>
    </ModalHandlersContext.Provider>
  );
};

export default ModalHandlersProvider;

目前子组件可以通过ModalHandlersContext提供的handlers方法完成弹窗的打开/关闭操作。

我知道可以在用户点击的跳转触发元素上绑定弹窗关闭方法(handlers.closeModal),但这种方式效率低下,也无法处理用户点击浏览器返回按钮触发跳转的场景。

我了解到Next.js中可以使用useRoute()解决该问题,但我作为React新手暂时不想尝试Next.js相关方案,请问针对当前技术栈有什么可行的解决方法?


解决方案

你当前使用的react-router-dom v6本身就自带路由监听能力,不需要引入额外框架,直接在ModalHandlersProvider里监听路由变化即可,所有跳转场景(包括点击链接、浏览器前进/返回、代码调用navigate跳转)都能覆盖到。

修改后的ModalHandlersProvider代码如下:

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

const ModalHandlersContext = React.createContext(initialState);
export const useModalHandlersContext = () => useContext(ModalHandlersContext);

const ModalHandlersProvider = ({ children }) => {
  const [modal, setModal] = useState(initialState);
  // 获取当前路由位置对象
  const location = useLocation();

  const handlers = {
    openModal: setModal,
    closeModal: () => setModal(initialState),
  };

  // 路由变化时自动关闭弹窗
  useEffect(() => {
    handlers.closeModal();
  }, [location.pathname, location.search]);

  return (
    <ModalHandlersContext.Provider value={handlers}>
      {children}
      <CustomModal
        open={modal.open}
        onClose={handlers.closeModal}
        content={modal.content}
      ></CustomModal>
    </ModalHandlersContext.Provider>
  );
};

export default ModalHandlersProvider;

实现说明

  • 依赖useLocation获取当前路由信息,只要pathname(路径)或者search(查询参数)发生变化,就会触发useEffect执行关闭弹窗的逻辑
  • 不需要在任何跳转按钮上额外绑定关闭方法,所有触发路由变更的操作都会自动触发弹窗关闭
  • 如果你的业务场景下同路径换查询参数不需要关闭弹窗,可以把location.search从useEffect依赖数组中移除;如果需要监听hash变化,也可以把location.hash加入依赖数组,按需调整即可

注意:要保证ModalHandlersProvider放在BrowserRouter内部,你当前的App组件结构刚好符合这个要求,不需要调整外层结构,直接修改Provider代码就能生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 20:09:34