使用react-router useNavigate跳转时Ant Design Message不显示的问题
Ant Design Message 跳转后不显示问题解决
问题场景
开发CRUD应用,页面结构为:
List |__Create |__Edit
复用Create/Edit表单组件,操作成功后需要完成两个动作:
- 显示Ant Design的Message提示
- 通过react-router的
useNavigate跳转回列表页
但执行跳转时消息完全不显示,不跳转则消息正常弹出。已尝试将Message的contextHolder移到列表页上层组件,未解决;添加async/await能让消息显示后再跳转,但需要同步逻辑的解决方案。
相关代码示例:
// CreateEditForm.tsx const navigate = useNavigate(); const [messageApi, contextHolder] = message.useMessage(); // 异步请求回调 onComplete: (data) => { if (data.error) { return messageApi.error('Error'); } messageApi.success('Success'); return navigate('/list') } // 渲染部分 return ( <> {contextHolder} <Form> {/* 表单内容 */} </Form> </> );
原因分析
- 上下文销毁:
contextHolder挂载在Create/Edit页面组件内,跳转后组件立即卸载,Message的上下文被销毁,导致消息无法渲染。 - 异步渲染被中断:
messageApi.success是异步触发DOM更新的操作,而navigate是同步执行的页面跳转,DOM还没来得及渲染消息就被卸载了。
解决方案
方案1:全局挂载contextHolder
将contextHolder移到整个应用的路由上层(比如App.tsx),确保页面跳转后上下文依然存在:
// App.tsx import { message } from 'antd'; function App() { const [, contextHolder] = message.useMessage(); return ( <> {contextHolder} <Routes> <Route path="/list" element={<ListPage />} /> <Route path="/create" element={<CreateEditForm />} /> <Route path="/edit/:id" element={<CreateEditForm />} /> </Routes> </> ); }
之后在CreateEditForm里只需要使用messageApi,不需要再渲染contextHolder。
方案2:利用Message的onClose回调跳转
在消息的关闭回调里执行跳转,确保消息显示完成后再触发页面跳转:
// CreateEditForm.tsx 回调部分修改 onComplete: (data) => { if (data.error) { return messageApi.error('Error'); } messageApi.success('Success', { onClose: () => { navigate('/list'); } }); }
这种方式不需要调整contextHolder的位置,且能保证消息正常显示后再跳转,体验更流畅。
方案3:延迟跳转(不推荐)
通过setTimeout给消息渲染留时间,缺点是需要硬编码延迟时间,不够优雅:
messageApi.success('Success'); setTimeout(() => navigate('/list'), 1500); // 匹配Message默认超时时间
内容的提问来源于stack exchange,提问作者nyphur
相关产品推荐
相关产品推荐

