如何在Ant Design Modal.method()中使用react-router-dom的useNavigate?
问题原因
Ant Design的Modal.info这类静态方法创建的弹窗,默认会挂载到document.body节点上,而你的Router组件仅包裹了应用内部的DOM结构,弹窗的DOM不在Router的上下文范围内,导致useNavigate()无法获取到Router提供的上下文,因此抛出错误。
解决方案
方案1:直接传递navigate函数到弹窗组件
在调用弹窗的组件中先获取navigate实例,再通过props传递给弹窗内容组件:
// App.js import { useNavigate } from 'react-router-dom'; import { Modal } from 'antd'; import CustomCpn from './CustomCpn'; function App() { const navigate = useNavigate(); const openModal = () => { Modal.info({ title: '测试弹窗', content: <CustomCpn navigate={navigate} />, onOk() {}, }); }; return ( <div className="App"> <button onClick={openModal}>打开弹窗</button> </div> ); }
然后在弹窗内容组件中直接使用传入的navigate:
// CustomCpn.js export default function CustomCpn({ navigate }) { const handleJump = () => { navigate('/target-page'); }; return <button onClick={handleJump}>跳转到目标页面</button>; }
方案2:修改Modal的挂载容器,使其处于Router上下文内
通过getContainer属性指定Modal的挂载容器为Router包裹范围内的DOM节点,让弹窗组件能获取到Router上下文:
// App.js import { useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { Modal } from 'antd'; import CustomCpn from './CustomCpn'; function App() { const modalContainer = useRef(null); const openModal = () => { Modal.info({ title: '测试弹窗', content: <CustomCpn />, // 指定挂载容器 getContainer: () => modalContainer.current, onOk() {}, }); }; return ( <div className="App"> <button onClick={openModal}>打开弹窗</button> {/* 用于挂载Modal的容器 */} <div ref={modalContainer}></div> </div> ); }
此时CustomCpn可以正常使用useNavigate:
// CustomCpn.js import { useNavigate } from 'react-router-dom'; export default function CustomCpn() { const navigate = useNavigate(); const handleJump = () => { navigate('/target-page'); }; return <button onClick={handleJump}>跳转到目标页面</button>; }
方案3:通过自定义Context共享navigate(适合多组件场景)
如果多个弹窗或组件都需要使用navigate,可以通过Context统一传递:
// NavigateContext.js import { createContext, useContext, useNavigate } from 'react-router-dom'; const NavigateContext = createContext(); export function NavigateProvider({ children }) { const navigate = useNavigate(); return ( <NavigateContext.Provider value={navigate}> {children} </NavigateContext.Provider> ); } export function useAppNavigate() { return useContext(NavigateContext); }
在Router内部包裹NavigateProvider:
// index.js import { BrowserRouter as Router } from 'react-router-dom'; import { NavigateProvider } from './NavigateContext'; import App from './App'; ReactDOM.render( <Router> <NavigateProvider> <App /> </NavigateProvider> </Router>, document.getElementById('root') );
最后在CustomCpn中使用自定义Hook获取navigate:
// CustomCpn.js import { useAppNavigate } from './NavigateContext'; export default function CustomCpn() { const navigate = useAppNavigate(); const handleJump = () => { navigate('/target-page'); }; return <button onClick={handleJump}>跳转到目标页面</button>; }
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

