如何导出useContext变量,无需每个组件调用useContext即可直接导入使用?
解决方案
可以实现你需要的直接导入toast对象的使用方式,具体实现思路和代码如下:
实现思路
我们可以在Toast Provider组件挂载时,把内部可用的toast实例赋值给模块顶层的共享变量,再基于这个变量封装统一的toast对象导出,外部导入后就可以直接调用对应的方法,不需要在每个组件内调用useToast钩子,原有Toast的渲染逻辑完全不需要改动。
完整代码修改示例
// toast-provider.tsx import { createContext, useContext, ReactNode, useEffect } from 'react'; // 你项目中原有的Toast实例类型,可根据实际需求扩展 type ToastType = { success: (message: string) => void; error: (message: string) => void; info: (message: string) => void; warning: (message: string) => void; } // 模块顶层的共享toast实例引用 let globalToastRef: ToastType | null = null; // 导出供外部直接调用的toast对象 export const toast: ToastType = { success: (message) => { if (!globalToastRef) { throw new Error('Toast未初始化,请确认项目根节点已包裹ToastProvider'); } globalToastRef.success(message); }, error: (message) => { if (!globalToastRef) { throw new Error('Toast未初始化,请确认项目根节点已包裹ToastProvider'); } globalToastRef.error(message); }, info: (message) => { if (!globalToastRef) { throw new Error('Toast未初始化,请确认项目根节点已包裹ToastProvider'); } globalToastRef.info(message); }, warning: (message) => { if (!globalToastRef) { throw new Error('Toast未初始化,请确认项目根节点已包裹ToastProvider'); } globalToastRef.warning(message); }, }; // 原有Context逻辑保留,不影响旧代码使用useToast const ToastContext = createContext<ToastType | undefined>(undefined); export const ToastProvider = ({ children }: { children: ReactNode }) => { // 你项目中原有的toast实例实现,包括维护消息队列、渲染弹窗等逻辑,不需要修改 const toastInstance: ToastType = { success: (msg) => { /* 原有成功提示逻辑 */ }, error: (msg) => { /* 原有错误提示逻辑 */ }, info: (msg) => { /* 原有信息提示逻辑 */ }, warning: (msg) => { /* 原有警告提示逻辑 */ }, }; // 组件挂载时将实例赋值给全局引用 useEffect(() => { globalToastRef = toastInstance; // 卸载时清空引用避免内存泄漏 return () => { globalToastRef = null; }; }, [toastInstance]); return ( <ToastContext.Provider value={toastInstance}> {children} {/* 原有Toast消息列表的渲染DOM */} </ToastContext.Provider> ); }; // 原有useToast钩子保留,兼容旧代码 export const useToast = () => { const context = useContext(ToastContext); if (!context) throw new Error('useToast必须在ToastProvider内部使用'); return context; };
注意事项
- 该方案的使用前提和原有用法一致,必须保证项目根节点已包裹
ToastProvider,否则调用toast方法会抛出未初始化错误 - Toast的渲染表现和原有方案完全一致,不会出现功能差异
- 若你的项目是服务端渲染(SSR/SSG)场景,服务端运行时不会执行客户端挂载逻辑,直接调用toast会报错,仅可在客户端侧执行的逻辑(如点击事件、useEffect回调)中调用
内容的提问来源于stack exchange,提问作者Lynxerious
相关产品推荐
相关产品推荐

