React项目中实现Telemetry Initializer用当前路由覆盖PageView名称
解决React中App Insights PageView名称固定问题及Hook调用错误
错误原因
你在telemetryInitializer中直接调用useLocation触发错误,是因为React Hook只能在函数组件的顶层或自定义Hook内部调用,而telemetryInitializer是在组件外部初始化的,不在React的组件渲染生命周期中,违反了Hook规则。
解决方案:手动监听路由并发送PageView
这种方式更直观,适合新手,且能准确控制PageView的名称:
步骤1:修改App Insights初始化配置
关闭自动路由追踪,避免和手动追踪重复:
import { AppInsightsContext, ReactPlugin, withAITracking } from '@microsoft/applicationinsights-react-js'; import { ApplicationInsights } from '@microsoft/applicationinsights-web'; import { BrowserRouter, useLocation, useContext, useEffect } from 'react-router-dom'; // <snip> 其他导入 const reactPlugin = new ReactPlugin(); const appInsights = new ApplicationInsights({ config: { connectionString: 'myconnectionstring', extensions: [reactPlugin], enableAutoRouteTracking: false, // 关键:关闭自动路由追踪 enableCorsCorrelation: true, enableRequestHeaderTracking: true, enableResponseHeaderTracking: true, }, }); appInsights.loadAppInsights();
步骤2:创建路由监听组件
这个组件负责监听路由变化,手动发送PageView:
// 创建专门的页面追踪组件 const TrackPageView: React.FC = () => { // 在组件内部合法使用useLocation const location = useLocation(); // 获取App Insights实例 const aiContext = useContext(AppInsightsContext); // 路由变化时触发PageView发送 useEffect(() => { if (aiContext) { aiContext.trackPageView({ name: location.pathname, // 用当前路由作为PageView名称 uri: location.pathname }); } }, [location.pathname, aiContext]); // 依赖路由路径和AI实例,变化时执行 return null; // 这个组件不需要渲染任何内容 };
步骤3:更新App组件结构
将TrackPageView组件放到BrowserRouter和AppInsightsContext.Provider内部,确保能获取到路由上下文和AI实例:
const App: React.FC = () => { return ( <Provider store={store}> <BrowserRouter> <AppInsightsContext.Provider value={reactPlugin}> {/* 添加路由追踪组件 */} <TrackPageView /> <AppBootstrap /> <ToastContainer /> </AppInsightsContext.Provider> </BrowserRouter> </Provider> ); }; export default withAITracking(reactPlugin, App);
备选方案:全局变量传递路由信息(不推荐)
如果你想保留自动路由追踪,可以通过全局变量传递当前路由给telemetryInitializer,但存在竞态风险,仅作参考:
// 全局变量存储当前路由 let currentPathname = '/'; // 初始化App Insights时保留自动追踪 const appInsights = new ApplicationInsights({ config: { connectionString: 'myconnectionstring', extensions: [reactPlugin], enableAutoRouteTracking: true, // 开启自动追踪 // 其他配置... }, }); appInsights.addTelemetryInitializer((envelope) => { const telemetryItem = envelope.data.baseData; if (envelope.name === 'Microsoft.ApplicationInsights.PageView') { telemetryItem.name = currentPathname; // 使用全局变量更新名称 } }); appInsights.loadAppInsights(); // 创建更新全局变量的组件 const UpdatePathname: React.FC = () => { const location = useLocation(); useEffect(() => { currentPathname = location.pathname; }, [location.pathname]); return null; }; // 在App组件中添加这个组件(位置同方案一的TrackPageView)
内容的提问来源于stack exchange,提问作者Owen
相关产品推荐
相关产品推荐

