Commit 1f672969 authored by Robert Knight's avatar Robert Knight

Add code to debug ThreadList effect exception

Add code to debug an error [1] triggered during an effect in the
`ThreadList` component.

When the effect is run, an attempt to get a reference to a DOM node
rendered by the component using `getElementById` is failing. This could
be because:

 - The component has been unmounted (I didn't think effects could run
   after unmounting, but I'm not certain)
 - The component has been rendered but the DOM has not yet been attached
   to the document
 - The `visibleThreads` value captured by the effect does not match the
   most recently rendered output.

I couldn't reproduce the issue locally. The debugging code added here
should narrow down which of these is happening.

[1] https://sentry.io/organizations/hypothesis/issues/2554918407/
parent 206803f8
import { useEffect, useLayoutEffect, useMemo, useState } from 'preact/hooks';
import {
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
} from 'preact/hooks';
import debounce from 'lodash.debounce';
import { useStoreProxy } from '../store/use-store';
......@@ -167,6 +173,8 @@ function ThreadList({ threads }) {
};
}, []);
const rootRef = useRef(/** @type {HTMLDivElement|null} */ (null));
// When the set of visible threads changes, recalculate the real rendered
// heights of thread cards and update `threadHeights` state if there are changes.
useEffect(() => {
......@@ -176,6 +184,31 @@ function ThreadList({ threads }) {
const threadElement = /** @type {HTMLElement} */ (
document.getElementById(id)
);
// Temporary code added to aid debugging of
// https://sentry.io/organizations/hypothesis/issues/2554918407/
/* istanbul ignore next */
if (!threadElement) {
const root = rootRef.current;
// Check if effect was called when ThreadList is not mounted.
if (!root) {
throw new Error(`Unable to measure thread ${id}. DOM not present.`);
}
// Check if effect was called when ThreadList is rendered but not
// connected to parent document.
if (!root.isConnected) {
throw new Error(
`Unable to measure thread ${id}. DOM not connected`
);
}
// Check if effect was called with `visibleThreads` value which does
// not match most recently rendered `visibleThreads`.
throw new Error(`Unable to measure thread ${id}. Element not found`);
}
const height = getElementHeightWithMargins(threadElement);
if (height !== prevHeights[id]) {
changedHeights[id] = height;
......@@ -193,7 +226,7 @@ function ThreadList({ threads }) {
}, [visibleThreads]);
return (
<div>
<div ref={rootRef}>
<div style={{ height: offscreenUpperHeight }} />
{visibleThreads.map(child => (
<div className="ThreadList__card" id={child.id} key={child.id}>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment