Troubleshooting

This page contains tips for issues that you may encounter while using custom widgets.

Page crashes

Custom widgets run inside an iframe and may crash if they consume too much memory or block the browser thread. When this occurs, the browser may become unresponsive or show a terminated state. Use the Performance tab in Chrome DevTools to record browser execution and look for performance anomalies.

Review the common anti-patterns described below to mitigate browser page crashing when working with custom widgets.

Avoid infinite loops and re-renders

Infinite or effectively infinite loops and re-renders are a common class of bug that can cause page crashes.

In React ↗, beware of loops that could cause infinite re-renders. Check for:

  • useEffect hooks that update a dependency of the same hook, causing them to run again.
  • setTimeout, setInterval, requestAnimationFrame loops that are never cleared.
  • Event handlers, such as window.addEventListener, that cause updates which trigger the same handler again.
  • Rendering code that performs expensive work for every item on every render.
Copied!
1 2 3 4 5 6 7 8 9 10 function InfiniteRender({ objects }: { objects: MyObject[] }) { const [data, setData] = useState<MyObject[]>([]); // BUG: updating data which is also a dependency useEffect(() => { setData([...objects]); }, [objects, data]); return <MyComponent />; }

Outside of React, avoid creating while loops that never exit:

Copied!
1 2 3 4 5 6 7 // BUG: infinite loop if condition is never met while (true) { doSomething(); if (myCondition) { break; } }

Additionally, you should not create while loops that are effectively infinite due to an unknown and unexpectedly large number of iterations:

Copied!
1 2 3 4 5 6 7 8 9 const minValue = min(myValues); const maxValue = max(myValues); let currentValue = minValue; // BUG: effectively infinite loop if bounds of myValues are unknown and unexpectedly large while (currentValue <= maxValue) { doSomething(currentValue); currentValue += 1; }

Avoid loading all data into the browser

When an ontology object type has a large number of objects, do not load all objects into the browser for client-side processing. This can exhaust browser resources and transfer large amounts of data over the network, which can be slow for widget users.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 let pageToken: string | undefined; const allObjects = []; do { const page = await client(MyObject).fetchPage({ $pageSize: 1_000, $pageToken: pageToken, }); allObjects.push(...page.data); pageToken = page.nextPageToken; } while (pageToken != null);

Instead:

  • Display a single page of data to the user and only load extra pages when needed.
  • Apply filtering and sorting in the query rather than in client-side processing.
  • Use aggregations when summary statistics, such as a total count, are required.
  • Request only the properties required with $select for object types with many properties.
  • Use derived properties through .withProperties for calculations depending on values of other properties or links on objects.