|
1 |
| -import React, { useEffect } from 'react' |
2 |
| -import ReactDOM from 'react-dom/client' |
| 1 | +import React, { useEffect, useState } from "react" |
| 2 | +import ReactDOM from "react-dom/client" |
3 | 3 | import {
|
4 | 4 | createBrowserRouter,
|
5 | 5 | RouterProvider,
|
6 | 6 | Link,
|
7 | 7 | Outlet
|
8 |
| -} from 'react-router-dom'; |
9 |
| -import BugsnagPerformance from '@bugsnag/browser-performance' |
10 |
| -import { ReactRouterRoutingProvider } from '@bugsnag/react-router-performance' |
| 8 | +} from "react-router-dom"; |
| 9 | +import BugsnagPerformance from "@bugsnag/browser-performance" |
| 10 | +import { ReactRouterRoutingProvider } from "@bugsnag/react-router-performance" |
| 11 | +import { withInstrumentedComponent } from "@bugsnag/plugin-react-performance" |
11 | 12 |
|
12 | 13 | const parameters = new URLSearchParams(window.location.search)
|
13 |
| -const apiKey = parameters.get('api_key') |
14 |
| -const endpoint = parameters.get('endpoint') |
| 14 | +const apiKey = parameters.get("api_key") |
| 15 | +const endpoint = parameters.get("endpoint") |
15 | 16 |
|
16 |
| -const basename = '/docs/react-router' |
| 17 | +const basename = "/docs/react-router" |
17 | 18 |
|
18 | 19 | function Root() {
|
19 | 20 | return (
|
20 | 21 | <>
|
21 | 22 | <Link id="change-route" to="/contacts/1">
|
22 | 23 | Contact 1
|
23 | 24 | </Link>
|
| 25 | + <Link id="change-route-component-spans" to="/component-lifecycle-spans"> |
| 26 | + Component Lifecycle Spans |
| 27 | + </Link> |
24 | 28 | <Outlet />
|
25 | 29 | </>
|
26 | 30 | )
|
27 | 31 | }
|
28 | 32 |
|
29 | 33 | function Contact() {
|
30 | 34 | useEffect(() => {
|
31 |
| - document.title = 'Contact 1' |
| 35 | + document.title = "Contact 1" |
32 | 36 | }, [])
|
33 | 37 |
|
34 | 38 | return <div id="contact">Contact</div>
|
35 | 39 | }
|
36 | 40 |
|
| 41 | +function Component({ count }) { |
| 42 | + return ( |
| 43 | + <div> |
| 44 | + <p>Wrapped Component</p> |
| 45 | + <p>count: {count}</p> |
| 46 | + </div> |
| 47 | + ) |
| 48 | +} |
| 49 | + |
| 50 | +const WrappedComponent = withInstrumentedComponent(Component) |
| 51 | + |
| 52 | +function KeepAlive() { |
| 53 | + useEffect(() => { |
| 54 | + // stop the page from settling until the 'stop-clock' button is |
| 55 | + // clicked, otherwise we can't reliably get a first input delay event |
| 56 | + |
| 57 | + const node = document.getElementById("clock") |
| 58 | + let time = 0 |
| 59 | + |
| 60 | + const interval = setInterval(() => { |
| 61 | + node.innerText += `${time++}\n` |
| 62 | + }, 50) |
| 63 | + |
| 64 | + document.getElementById("stop-clock").addEventListener("click", () => { |
| 65 | + document.title = "New title" |
| 66 | + |
| 67 | + // delay stopping the clock for a bit so the performance observers |
| 68 | + // have a chance to fire |
| 69 | + setTimeout(() => { clearInterval(interval) }, 1000) |
| 70 | + }) |
| 71 | + |
| 72 | + return () => { |
| 73 | + clearInterval(interval) |
| 74 | + } |
| 75 | + }, []) |
| 76 | + |
| 77 | + return ( |
| 78 | + <div> |
| 79 | + <button id="stop-clock">Stop</button> |
| 80 | + <pre id="clock"></pre> |
| 81 | + <p>I'm here to make the layout shift when the clock ticks</p> |
| 82 | + </div> |
| 83 | + ) |
| 84 | +} |
| 85 | + |
| 86 | +function ComponentLifecycleSpans() { |
| 87 | + const [show, setShow] = useState(true) |
| 88 | + const [count, setCount] = useState(0) |
| 89 | + |
| 90 | + return ( |
| 91 | + <div id="component-lifecycle-spans"> |
| 92 | + <h1>Component Lifecycle Spans</h1> |
| 93 | + <button id="update-props" onClick={() => { setCount(n => n + 1) }}>Update props</button> |
| 94 | + <button id="hide-component" onClick={() => { setShow(n => !n) }}>Hide component</button> |
| 95 | + {show ? <WrappedComponent count={count} /> : null} |
| 96 | + <KeepAlive /> |
| 97 | + </div> |
| 98 | + ) |
| 99 | +} |
| 100 | + |
37 | 101 | const routes = [
|
38 |
| - { |
39 |
| - path: '/', |
40 |
| - element: <Root />, |
41 |
| - children: [ |
42 |
| - { |
43 |
| - path: 'contacts/:contactId', |
44 |
| - element: <Contact />, |
45 |
| - }, |
46 |
| - ] |
47 |
| - }, |
| 102 | + { |
| 103 | + path: "/", |
| 104 | + element: <Root />, |
| 105 | + children: [ |
| 106 | + { |
| 107 | + path: "contacts/:contactId", |
| 108 | + element: <Contact /> |
| 109 | + }, |
| 110 | + { |
| 111 | + path: "component-lifecycle-spans", |
| 112 | + element: <ComponentLifecycleSpans /> |
| 113 | + } |
| 114 | + ] |
| 115 | + } |
48 | 116 | ]
|
49 | 117 |
|
50 | 118 | const router = createBrowserRouter(routes, { basename })
|
51 | 119 |
|
52 | 120 | BugsnagPerformance.start({
|
53 | 121 | apiKey,
|
54 | 122 | endpoint,
|
55 |
| - maximumBatchSize: 2, |
| 123 | + maximumBatchSize: 6, |
56 | 124 | batchInactivityTimeoutMs: 5000,
|
57 | 125 | autoInstrumentFullPageLoads: false,
|
58 | 126 | autoInstrumentNetworkRequests: false,
|
59 | 127 | routingProvider: new ReactRouterRoutingProvider(routes, basename)
|
60 | 128 | })
|
61 | 129 |
|
62 |
| -ReactDOM.createRoot(document.getElementById('root')).render( |
| 130 | +ReactDOM.createRoot(document.getElementById("root")).render( |
63 | 131 | <React.StrictMode>
|
64 | 132 | <RouterProvider router={router} />
|
65 | 133 | </React.StrictMode>,
|
|
0 commit comments