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
相关产品推荐
相关产品推荐

