mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-22 15:39:11 +00:00
perf(cuesheet): revert lazy-autosize (Exp B) — metrics show it regresses
Measured baseline vs lazy-autosize at CPU 4x (median of 3, ~1140 row mounts): - cell.autosize eliminated (15.2s -> 0) BUT - EventRow.mount avg +39% (179 -> 248ms), longtask +32%, longFrames 201->219, and per-row re-renders ~2x (getVisibleCells renders 4648 -> 8902). Deferring autosize destabilises virtuoso row-height measurement (rows=1 textareas), causing more re-render churn, and collapses note display. Net negative — not merged. Keeping instrumented baseline.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
// @ts-expect-error no types from library
|
// @ts-expect-error no types from library
|
||||||
import autosize from 'autosize/dist/autosize';
|
import autosize from 'autosize/dist/autosize';
|
||||||
import { FocusEvent, RefObject, useCallback, useEffect } from 'react';
|
import { RefObject, useEffect } from 'react';
|
||||||
|
|
||||||
import { timeSync } from '../../../devtools/cuesheet-metrics/usePerfMark'; // PERF-METRICS
|
import { timeSync } from '../../../devtools/cuesheet-metrics/usePerfMark'; // PERF-METRICS
|
||||||
import Textarea, { type TextareaProps } from '../textarea/Textarea';
|
import Textarea, { type TextareaProps } from '../textarea/Textarea';
|
||||||
@@ -10,41 +10,18 @@ interface AutoTextAreaProps extends TextareaProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A textarea that automatically resizes based on its content.
|
* A textarea that automatically resizes based on its content
|
||||||
*
|
|
||||||
* `autosize()` forces a synchronous reflow (reads scrollHeight) and installs a MutationObserver.
|
|
||||||
* Doing that on mount makes it expensive when many of these are mounted at once (e.g. virtualised
|
|
||||||
* table rows during scroll), so we only attach autosize while the field is focused for editing and
|
|
||||||
* keep it in sync with the value during that time.
|
|
||||||
*/
|
*/
|
||||||
export function AutoTextarea({ value, inputref, onFocus, onBlur, ...textAreaProps }: AutoTextAreaProps) {
|
export function AutoTextarea({ value, inputref, ...textAreaProps }: AutoTextAreaProps) {
|
||||||
const handleFocus = useCallback(
|
// when the value changes, we use the ref to reapply autosize
|
||||||
(event: FocusEvent<HTMLTextAreaElement>) => {
|
|
||||||
timeSync('cell.autosize', () => autosize(inputref.current)); // PERF-METRICS
|
|
||||||
onFocus?.(event);
|
|
||||||
},
|
|
||||||
[inputref, onFocus],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleBlur = useCallback(
|
|
||||||
(event: FocusEvent<HTMLTextAreaElement>) => {
|
|
||||||
if (inputref.current) {
|
|
||||||
autosize.destroy(inputref.current);
|
|
||||||
}
|
|
||||||
onBlur?.(event);
|
|
||||||
},
|
|
||||||
[inputref, onBlur],
|
|
||||||
);
|
|
||||||
|
|
||||||
// while focused, keep the height in sync as the value changes
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const node = inputref.current;
|
const node = inputref.current;
|
||||||
if (node && document.activeElement === node) {
|
timeSync('cell.autosize', () => autosize(inputref.current)); // PERF-METRICS
|
||||||
autosize(node);
|
|
||||||
}
|
return () => {
|
||||||
|
autosize.destroy(node);
|
||||||
|
};
|
||||||
}, [inputref, value]);
|
}, [inputref, value]);
|
||||||
|
|
||||||
return (
|
return <Textarea ref={inputref} value={value} {...textAreaProps} />;
|
||||||
<Textarea ref={inputref} value={value} onFocus={handleFocus} onBlur={handleBlur} {...textAreaProps} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user