@multiplayer-app/session-recorder-react 1.2.24 → 1.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -57
- package/dist/ErrorBoundary.d.ts +17 -0
- package/dist/ErrorBoundary.d.ts.map +1 -0
- package/dist/ErrorBoundary.js +27 -0
- package/dist/ErrorBoundary.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/ErrorBoundary.tsx +38 -0
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -51,18 +51,18 @@ To get full‑stack session recording working, set up one of our backend SDKs/CL
|
|
|
51
51
|
|
|
52
52
|
## Quick start
|
|
53
53
|
|
|
54
|
-
1.
|
|
55
|
-
2.
|
|
54
|
+
1. Recommended: Call `SessionRecorder.init(options)` before you mount your React app to avoid losing any data.
|
|
55
|
+
2. Wrap your application with the `SessionRecorderProvider`.
|
|
56
56
|
3. Start or stop sessions using the widget or the provided hooks.
|
|
57
57
|
|
|
58
|
-
### Minimal setup with manual initialization
|
|
58
|
+
### Minimal setup with manual initialization (Recommended)
|
|
59
59
|
|
|
60
60
|
```tsx
|
|
61
61
|
// src/main.tsx or src/index.tsx app root
|
|
62
62
|
import React from 'react'
|
|
63
63
|
import ReactDOM from 'react-dom/client'
|
|
64
64
|
import App from './App'
|
|
65
|
-
import { SessionRecorderProvider } from '@multiplayer-app/session-recorder-react'
|
|
65
|
+
import SessionRecorder, { SessionRecorderProvider } from '@multiplayer-app/session-recorder-react'
|
|
66
66
|
|
|
67
67
|
const sessionRecorderConfig = {
|
|
68
68
|
version: '1.0.0',
|
|
@@ -77,8 +77,8 @@ const sessionRecorderConfig = {
|
|
|
77
77
|
propagateTraceHeaderCorsUrls: [new RegExp('https://api.example.com', 'i')]
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// Initialize the session recorder
|
|
81
|
-
|
|
80
|
+
// Initialize the session recorder before mounting (Recommended)
|
|
81
|
+
SessionRecorder.init(sessionRecorderConfig)
|
|
82
82
|
|
|
83
83
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
84
84
|
<SessionRecorderProvider>
|
|
@@ -87,30 +87,7 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
87
87
|
)
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
```tsx
|
|
93
|
-
// src/main.tsx or src/index.tsx app root
|
|
94
|
-
import React from 'react'
|
|
95
|
-
import ReactDOM from 'react-dom/client'
|
|
96
|
-
import App from './App'
|
|
97
|
-
import { SessionRecorderProvider } from '@multiplayer-app/session-recorder-react'
|
|
98
|
-
|
|
99
|
-
const sessionRecorderConfig = {
|
|
100
|
-
version: '1.0.0',
|
|
101
|
-
environment: 'production',
|
|
102
|
-
application: 'my-react-app',
|
|
103
|
-
apiKey: 'YOUR_MULTIPLAYER_API_KEY'
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
107
|
-
<SessionRecorderProvider options={sessionRecorderConfig}>
|
|
108
|
-
<App />
|
|
109
|
-
</SessionRecorderProvider>
|
|
110
|
-
)
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Behind the scenes, the provider initializes the shared Browser SDK (if you pass the configuration as options to the provider) — or you can initialize it manually as shown in the example above. It then sets up listeners and exposes helper APIs through React context and selectors.
|
|
90
|
+
Behind the scenes, the provider sets up listeners and exposes helper APIs through React context and selectors.
|
|
114
91
|
|
|
115
92
|
### Set session attributes to provide context for the session
|
|
116
93
|
|
|
@@ -140,16 +117,19 @@ const MyComponent = () => {
|
|
|
140
117
|
If you prefer not to render our floating widget, disable it and rely purely on the imperative hooks. Use the context hook when you need imperative control (for example, to bind to buttons or QA tooling) as shown in the example below:
|
|
141
118
|
|
|
142
119
|
```tsx
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
120
|
+
import SessionRecorder, { SessionRecorderProvider } from '@multiplayer-app/session-recorder-react'
|
|
121
|
+
|
|
122
|
+
// Initialize without the built‑in widget
|
|
123
|
+
SessionRecorder.init({
|
|
124
|
+
application: 'my-react-app',
|
|
125
|
+
version: '1.0.0',
|
|
126
|
+
environment: 'production',
|
|
127
|
+
apiKey: 'YOUR_MULTIPLAYER_API_KEY',
|
|
128
|
+
showWidget: false // hide the built-in widget
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// Wrap your app with the provider to enable hooks/context
|
|
132
|
+
<SessionRecorderProvider>
|
|
153
133
|
<App />
|
|
154
134
|
</SessionRecorderProvider>
|
|
155
135
|
```
|
|
@@ -279,7 +259,7 @@ export function NavigationTrackerLegacy() {
|
|
|
279
259
|
|
|
280
260
|
## Configuration reference
|
|
281
261
|
|
|
282
|
-
The
|
|
262
|
+
The options passed to `SessionRecorder.init(...)` are forwarded to the underlying browser SDK. Refer to the [browser README](../session-recorder-browser/README.md#initialize) for the full option list, including:
|
|
283
263
|
|
|
284
264
|
- `application`, `version`, `environment`, `apiKey`
|
|
285
265
|
- `showWidget`, `showContinuousRecording`
|
|
@@ -290,6 +270,74 @@ The `options` prop passed to `SessionRecorderProvider` is forwarded to the under
|
|
|
290
270
|
|
|
291
271
|
Any time `recordNavigation` is enabled, the browser SDK will emit OpenTelemetry navigation spans and keep an in-memory stack of visited routes. You can access the navigation helpers through `SessionRecorder.navigation` if you need to introspect from React components.
|
|
292
272
|
|
|
273
|
+
## Capturing exceptions in React apps
|
|
274
|
+
|
|
275
|
+
The browser SDK auto‑captures uncaught errors and unhandled promise rejections. In React apps you’ll typically also want an Error Boundary to catch render errors and report them. This package ships a ready‑to‑use boundary and also shows how to wire React 18/19 root error callbacks.
|
|
276
|
+
|
|
277
|
+
### Using the built‑in error boundary
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
import React from 'react'
|
|
281
|
+
import { ErrorBoundary } from '@multiplayer-app/session-recorder-react'
|
|
282
|
+
|
|
283
|
+
export function AppWithBoundary() {
|
|
284
|
+
return (
|
|
285
|
+
<ErrorBoundary fallback={<div>Something went wrong</div>}>
|
|
286
|
+
<App />
|
|
287
|
+
</ErrorBoundary>
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The boundary calls `SessionRecorder.captureException(error)` internally and renders the provided `fallback` on error.
|
|
293
|
+
|
|
294
|
+
### Custom boundary (if you need full control)
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import React from 'react'
|
|
298
|
+
import SessionRecorder from '@multiplayer-app/session-recorder-react'
|
|
299
|
+
|
|
300
|
+
class MyErrorBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean }> {
|
|
301
|
+
state = { hasError: false }
|
|
302
|
+
static getDerivedStateFromError() {
|
|
303
|
+
return { hasError: true }
|
|
304
|
+
}
|
|
305
|
+
componentDidCatch(error: unknown) {
|
|
306
|
+
SessionRecorder.captureException(error as any)
|
|
307
|
+
}
|
|
308
|
+
render() {
|
|
309
|
+
return this.state.hasError ? <h1>Oops.</h1> : this.props.children
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### React 18/19 root error hooks
|
|
315
|
+
|
|
316
|
+
React surfaces recoverable runtime errors via the root option `onRecoverableError`. You can forward these to the session recorder as well. This works in React 18 and React 19.
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
import React from 'react'
|
|
320
|
+
import ReactDOM from 'react-dom/client'
|
|
321
|
+
import SessionRecorder from '@multiplayer-app/session-recorder-react'
|
|
322
|
+
import App from './App'
|
|
323
|
+
|
|
324
|
+
SessionRecorder.init({
|
|
325
|
+
/* ... your config ... */
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
ReactDOM.createRoot(document.getElementById('root')!, {
|
|
329
|
+
onRecoverableError(error) {
|
|
330
|
+
SessionRecorder.captureException(error as any)
|
|
331
|
+
}
|
|
332
|
+
}).render(<App />)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Notes:
|
|
336
|
+
|
|
337
|
+
- Uncaught errors and unhandled rejections are captured automatically by the browser SDK.
|
|
338
|
+
- Error Boundary + `onRecoverableError` covers both render and runtime recoverable errors.
|
|
339
|
+
- In Continuous mode, any captured exception marks the trace as ERROR and auto‑saves the rolling session window.
|
|
340
|
+
|
|
293
341
|
## Next.js integration tips
|
|
294
342
|
|
|
295
343
|
- Initialize the provider in a Client Component (for example `app/providers.tsx`) because the browser SDK requires `window`.
|
|
@@ -300,27 +348,24 @@ Any time `recordNavigation` is enabled, the browser SDK will emit OpenTelemetry
|
|
|
300
348
|
|
|
301
349
|
An official Next.js-specific wrapper is coming soon. Until then, you can use this package safely in Next.js by:
|
|
302
350
|
|
|
303
|
-
1. Initializing in a Client Component
|
|
351
|
+
1. Initializing in a Client Component (Recommended)
|
|
304
352
|
|
|
305
353
|
```tsx
|
|
306
354
|
'use client'
|
|
307
355
|
import React from 'react'
|
|
308
|
-
import { SessionRecorderProvider } from '@multiplayer-app/session-recorder-react'
|
|
356
|
+
import SessionRecorder, { SessionRecorderProvider } from '@multiplayer-app/session-recorder-react'
|
|
357
|
+
|
|
358
|
+
// Initialize before mount to avoid losing any data
|
|
359
|
+
SessionRecorder.init({
|
|
360
|
+
application: 'my-next-app',
|
|
361
|
+
version: '1.0.0',
|
|
362
|
+
environment: 'production',
|
|
363
|
+
apiKey: 'YOUR_MULTIPLAYER_API_KEY',
|
|
364
|
+
showWidget: true
|
|
365
|
+
})
|
|
309
366
|
|
|
310
367
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
311
|
-
return
|
|
312
|
-
<SessionRecorderProvider
|
|
313
|
-
options={{
|
|
314
|
-
application: 'my-next-app',
|
|
315
|
-
version: '1.0.0',
|
|
316
|
-
environment: 'production',
|
|
317
|
-
apiKey: 'YOUR_MULTIPLAYER_API_KEY',
|
|
318
|
-
showWidget: true
|
|
319
|
-
}}
|
|
320
|
-
>
|
|
321
|
-
{children}
|
|
322
|
-
</SessionRecorderProvider>
|
|
323
|
-
)
|
|
368
|
+
return <SessionRecorderProvider>{children}</SessionRecorderProvider>
|
|
324
369
|
}
|
|
325
370
|
```
|
|
326
371
|
|
|
@@ -377,7 +422,7 @@ All hooks and helpers ship with TypeScript types. To extend the navigation metad
|
|
|
377
422
|
## Troubleshooting
|
|
378
423
|
|
|
379
424
|
- Ensure the provider wraps your entire component tree so context hooks resolve.
|
|
380
|
-
- Confirm `SessionRecorder.init` runs only once
|
|
425
|
+
- Confirm `SessionRecorder.init` runs only once and before your app mounts.
|
|
381
426
|
- Ensure the session recorder required options are passed and the API key is valid.
|
|
382
427
|
- For SSR environments, guard any direct `document` or `window` usage behind `typeof window !== 'undefined'` checks (the helper hooks already do this).
|
|
383
428
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ErrorBoundaryProps = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
/** Optional fallback UI to render when an error is caught */
|
|
5
|
+
fallback?: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
type State = {
|
|
8
|
+
hasError: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {
|
|
11
|
+
constructor(props: ErrorBoundaryProps);
|
|
12
|
+
static getDerivedStateFromError(): State;
|
|
13
|
+
componentDidCatch(error: unknown): void;
|
|
14
|
+
render(): React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export default ErrorBoundary;
|
|
17
|
+
//# sourceMappingURL=ErrorBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../src/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B,CAAA;AAED,KAAK,KAAK,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAA;AAElC,qBAAa,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,KAAK,CAAC;gBAC/D,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,IAAI,KAAK;IAIxC,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAQvC,MAAM,IAAI,KAAK,CAAC,SAAS;CAM1B;AAED,eAAe,aAAa,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import SessionRecorder from '@multiplayer-app/session-recorder-browser';
|
|
3
|
+
export class ErrorBoundary extends React.Component {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.state = { hasError: false };
|
|
7
|
+
}
|
|
8
|
+
static getDerivedStateFromError() {
|
|
9
|
+
return { hasError: true };
|
|
10
|
+
}
|
|
11
|
+
componentDidCatch(error) {
|
|
12
|
+
try {
|
|
13
|
+
SessionRecorder.captureException(error);
|
|
14
|
+
}
|
|
15
|
+
catch (_e) {
|
|
16
|
+
// no-op
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
render() {
|
|
20
|
+
if (this.state.hasError) {
|
|
21
|
+
return this.props.fallback ?? null;
|
|
22
|
+
}
|
|
23
|
+
return this.props.children;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export default ErrorBoundary;
|
|
27
|
+
//# sourceMappingURL=ErrorBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.js","sourceRoot":"","sources":["../src/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,eAAe,MAAM,2CAA2C,CAAA;AAUvE,MAAM,OAAO,aAAc,SAAQ,KAAK,CAAC,SAAoC;IAC3E,YAAY,KAAyB;QACnC,KAAK,CAAC,KAAK,CAAC,CAAA;QACZ,IAAI,CAAC,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;IAClC,CAAC;IAED,MAAM,CAAC,wBAAwB;QAC7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IAC3B,CAAC;IAED,iBAAiB,CAAC,KAAc;QAC9B,IAAI,CAAC;YACH,eAAe,CAAC,gBAAgB,CAAC,KAAY,CAAC,CAAA;QAChD,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,QAAQ;QACV,CAAC;IACH,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAA;QACpC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAA;IAC5B,CAAC;CACF;AAED,eAAe,aAAa,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from '@multiplayer-app/session-recorder-browser';
|
|
|
2
2
|
export { default } from '@multiplayer-app/session-recorder-browser';
|
|
3
3
|
export * from './context/SessionRecorderContext';
|
|
4
4
|
export * from './context/useSessionRecorderStore';
|
|
5
|
+
export { ErrorBoundary } from './ErrorBoundary';
|
|
5
6
|
export { useNavigationRecorder } from './navigation';
|
|
6
7
|
export type { UseNavigationRecorderOptions } from './navigation';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AAEpE,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AAEpE,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACpD,YAAY,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,6 @@ export * from '@multiplayer-app/session-recorder-browser';
|
|
|
2
2
|
export { default } from '@multiplayer-app/session-recorder-browser';
|
|
3
3
|
export * from './context/SessionRecorderContext';
|
|
4
4
|
export * from './context/useSessionRecorderStore';
|
|
5
|
+
export { ErrorBoundary } from './ErrorBoundary';
|
|
5
6
|
export { useNavigationRecorder } from './navigation';
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AAEpE,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AAEpE,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplayer-app/session-recorder-react",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.26",
|
|
4
4
|
"description": "Multiplayer Fullstack Session Recorder for React (browser wrapper)",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Multiplayer Software, Inc.",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@opentelemetry/api": "^1.9.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@multiplayer-app/session-recorder-browser": "1.2.
|
|
39
|
-
"@multiplayer-app/session-recorder-common": "1.2.
|
|
38
|
+
"@multiplayer-app/session-recorder-browser": "1.2.26",
|
|
39
|
+
"@multiplayer-app/session-recorder-common": "1.2.26"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"eslint": "8.48.0",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import SessionRecorder from '@multiplayer-app/session-recorder-browser'
|
|
3
|
+
|
|
4
|
+
export type ErrorBoundaryProps = {
|
|
5
|
+
children: React.ReactNode
|
|
6
|
+
/** Optional fallback UI to render when an error is caught */
|
|
7
|
+
fallback?: React.ReactNode
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type State = { hasError: boolean }
|
|
11
|
+
|
|
12
|
+
export class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {
|
|
13
|
+
constructor(props: ErrorBoundaryProps) {
|
|
14
|
+
super(props)
|
|
15
|
+
this.state = { hasError: false }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getDerivedStateFromError(): State {
|
|
19
|
+
return { hasError: true }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
componentDidCatch(error: unknown): void {
|
|
23
|
+
try {
|
|
24
|
+
SessionRecorder.captureException(error as any)
|
|
25
|
+
} catch (_e) {
|
|
26
|
+
// no-op
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
render(): React.ReactNode {
|
|
31
|
+
if (this.state.hasError) {
|
|
32
|
+
return this.props.fallback ?? null
|
|
33
|
+
}
|
|
34
|
+
return this.props.children
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default ErrorBoundary
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,6 @@ export { default } from '@multiplayer-app/session-recorder-browser';
|
|
|
3
3
|
|
|
4
4
|
export * from './context/SessionRecorderContext';
|
|
5
5
|
export * from './context/useSessionRecorderStore';
|
|
6
|
-
|
|
6
|
+
export { ErrorBoundary } from './ErrorBoundary'
|
|
7
7
|
export { useNavigationRecorder } from './navigation'
|
|
8
8
|
export type { UseNavigationRecorderOptions } from './navigation'
|