Fix race condition in Timeline

Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
This commit is contained in:
automated-signal 2022-03-16 14:37:32 -07:00 committed by GitHub
parent 7c53ac21e8
commit bdc1cf0e4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 25 additions and 1 deletions

View File

@ -269,6 +269,7 @@ export class Timeline extends React.Component<
private readonly atBottomDetectorRef = React.createRef<HTMLDivElement>();
private readonly lastSeenIndicatorRef = React.createRef<HTMLDivElement>();
private intersectionObserver?: IntersectionObserver;
private intersectionObserverCallbackFrame?: number;
// This is a best guess. It will likely be overridden when the timeline is measured.
private maxVisibleRows = Math.ceil(window.innerHeight / MIN_ROW_HEIGHT);
@ -402,6 +403,10 @@ export class Timeline extends React.Component<
// this another way, but this approach works.)
this.intersectionObserver?.disconnect();
if (this.intersectionObserverCallbackFrame !== undefined) {
window.cancelAnimationFrame(this.intersectionObserverCallbackFrame);
}
const intersectionRatios = new Map<Element, number>();
const intersectionObserverCallback: IntersectionObserverCallback =
@ -492,7 +497,26 @@ export class Timeline extends React.Component<
};
this.intersectionObserver = new IntersectionObserver(
intersectionObserverCallback,
(entries, observer) => {
assert(
this.intersectionObserver === observer,
'observer.disconnect() should prevent callbacks from firing'
);
// `react-measure` schedules the callbacks on the next tick and so
// should we because we want other parts of this component to respond
// to resize events before we recalculate what is visible.
this.intersectionObserverCallbackFrame = window.requestAnimationFrame(
() => {
// Observer was updated from under us
if (this.intersectionObserver !== observer) {
return;
}
intersectionObserverCallback(entries, observer);
}
);
},
{
root: containerEl,
threshold: [0, 1],