如何在子组件中调用函数将ToastrNotification注入到根节点渲染
实现方案
该需求完全可以实现,核心依赖React内置的Portal API实现跨层级渲染,配合简单的节点调度逻辑即可完成调用式触发通知的效果。
实现步骤
第一步:预留全局通知挂载节点
可以直接在入口HTML文件的body中添加<div id="toastr-container"></div>,也可以直接在逻辑中动态创建该节点。第二步:实现
showToastrNotification方法
import { render, createPortal } from 'react-dom'; import { ToastrNotification } from './mycomponents'; // 优先获取已有的挂载容器,不存在则动态创建 let toastrContainer = document.getElementById('toastr-container'); if (!toastrContainer) { toastrContainer = document.createElement('div'); toastrContainer.id = 'toastr-container'; document.body.appendChild(toastrContainer); } export const showToastrNotification = (config: {heading: string, info: string, duration?: number}) => { // 为单条通知创建临时挂载节点 const notificationNode = document.createElement('div'); toastrContainer.appendChild(notificationNode); // 通知销毁逻辑 const destroy = () => { render(null, notificationNode); notificationNode.remove(); }; // 通过Portal将通知组件渲染到全局根级节点,而非调用方组件内部 render( createPortal( <ToastrNotification onClose={destroy}> <h3>{config.heading}</h3> <p>{config.info}</p> </ToastrNotification>, notificationNode ), notificationNode ); // 默认3秒后自动关闭通知 setTimeout(destroy, config.duration || 3000); };
如果使用的是React 18+版本,需要将上述的render方法替换为createRoot写法,避免控制台告警:
import { createRoot } from 'react-dom/client'; // 渲染部分替换为如下逻辑 const root = createRoot(notificationNode); root.render( createPortal( <ToastrNotification onClose={destroy}> <h3>{config.heading}</h3> <p>{config.info}</p> </ToastrNotification>, notificationNode ) ); // 销毁时调用 root.unmount() 即可
- 第三步:在业务组件中直接调用即可
export const MyComponent = (props:any) => { const showNotification = () => { showToastrNotification({ heading:"Success", info: "This is a success notification" }); }; return <button onClick={showNotification}>弹出成功通知</button>; };
其他框架适配说明
如果使用Vue、Angular等其他框架,也有对应逻辑的传送门API(Vue的Teleport、Angular的Portal),实现思路完全一致。
内容的提问来源于stack exchange,提问作者code0x00
相关产品推荐
相关产品推荐

