Quickly toggling the visibility of a component causes `measureElement` to return `NaN` until the next rerender
AlCalzone opened this issue · 1 comments
AlCalzone commented
I managed to narrow down the issue to this repro:
import { Box, DOMElement, measureElement, render, Text, useInput } from "ink";
import { useEffect, useRef, useState } from "react";
const Measured: React.FC = (props) => {
const ref = useRef<DOMElement>(null);
const [height, setHeight] = useState(0);
useEffect(() => {
if (ref.current) {
setHeight(measureElement(ref.current).height);
}
}, [ref.current]);
return (
<Box ref={ref} borderColor="red" borderStyle="round">
<Text>
My height is {height}. {Number.isNaN(height) && "It should be 3."}
</Text>
</Box>
);
};
const Root: React.FC = () => {
const [flicker, setFlicker] = useState(false);
const [show, setShow] = useState(false);
useInput((input, key) => {
if (input === "f") {
setFlicker((flicker) => !flicker);
} else if (input === "t") {
setShow((show) => !show);
// If this is enabled, the issue will happen
if (flicker) {
setTimeout(() => {
setShow((show) => !show);
}, 3);
setTimeout(() => {
setShow((show) => !show);
}, 7);
}
}
});
return (
<Box flexDirection="column">
<Box flexGrow={1} flexDirection="column">
<Text>
Problem is{flicker ? "" : " not"} active. Press{" "}
<Text bold color="red">
F
</Text>{" "}
to {flicker ? "de" : ""}activate it.
</Text>
<Text>
Press{" "}
<Text bold color="red">
T
</Text>{" "}
to toggle visibility of the measured element.
</Text>
</Box>
{show && <Measured />}
</Box>
);
};
render(<Root />);
This lets you toggle two states.
One (toggled with T) shows or hides an element that measures its own size using measureElement
.
The other (toggled with F) changes how the visibility of an element is toggled - either simply on / off, or "on-off-on" / "off-on-off". The latter will cause the measured element to think it has a size of NaN
.
Here's a video demonstrating the issue:
ink-repro-1678791145851.mp4
vadimdemedes commented
Thanks for a detailed issue report! That allowed me to quickly find and fix the root cause → #561.