Need Help: ‘getBoundingClientRect’ Error on Screen Resize

const COLOR_BY_ARRAY_NAME = "E_Mises";
const LOCATION = "PointData";
const PRESET_NAME = "erdc_rainbow_bright";
const AXIS_LABEL = "Von Mises Stress";

function VTKViewer({ requestId }) {
  const vtkContainerRef = useRef(null);
  const context = useRef(null);
  const navigate = useNavigate();
  const [representation, setRepresentation] = useState(2);
  const [minStress, setMinStress] = useState(null);
  const [maxStress, setMaxStress] = useState(null);
  const [loading, setLoading] = useState(false);

  const initializeVTK = async () => {
    setLoading(true);
    if (!context.current) {
      const container = vtkContainerRef.current;
      if (!container) {
        return;
      }
      const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
        background: [255, 255, 255],
        rootContainer: container,
        containerStyle: { height: "100%", width: "100%", position: "absolute" },
      });

      const reader = vtkXMLPolyDataReader.newInstance();

      try {
        const data = await fetchFileData(requestId);
        if (!container) {
          return;
        }
        let encoder = new TextEncoder();
        let arrayBuffer = encoder.encode(data.fileData).buffer;
        reader.parseAsArrayBuffer(arrayBuffer);
        const output = reader.getOutputData(0);
        const scalars = output.getPointData().getScalars();
        const dataRange = [].concat(scalars ? scalars.getRange() : [0, 1]);

        let activeArray = vtkDataArray;
        const newArray =
          output[`get${LOCATION}`]().getArrayByName(COLOR_BY_ARRAY_NAME);
        activeArray = newArray;
        const newDataRange = activeArray.getRange();
        dataRange[0] = newDataRange[0];
        dataRange[1] = newDataRange[1];

        setMinStress(data.minValue);
        setMaxStress(data.maxValue);

        const preset = vtkColorMaps.getPresetByName(PRESET_NAME);
        const lookupTable = vtkColorTransferFunction.newInstance();
        lookupTable.applyColorMap(preset);
        lookupTable.setMappingRange(dataRange[0], dataRange[1]);
        lookupTable.updateRange();

        const mapper = vtkMapper.newInstance();
        mapper.set({
          colorByArrayName: COLOR_BY_ARRAY_NAME,
          colorMode: ColorMode.MAP_SCALARS,
          interpolateScalarsBeforeMapping: true,
          scalarMode: ScalarMode.USE_POINT_FIELD_DATA,
          lookupTable,
          useLookupTableScalarRange: true,
          scalarVisibility: true,
        });

        mapper.setInputData(output);

        const actor = vtkActor.newInstance();
        actor.setMapper(mapper);

        const scalarBarActor = vtkScalarBarActor.newInstance();
        scalarBarActor.setScalarsToColors(lookupTable);
        scalarBarActor.setDrawNanAnnotation(false);
        scalarBarActor.setAxisLabel(AXIS_LABEL);
        scalarBarActor.setVisibility(true);
        scalarBarActor.setAxisTextStyle({
          fontColor: "black",
          fontFamily: "Arial",
        });
        scalarBarActor.setTickTextStyle({
          fontColor: "blue",
          fontFamily: "Arial",
        });

        const renderer = fullScreenRenderer.getRenderer();
        const renderWindow = fullScreenRenderer.getRenderWindow();

        renderer.addActor(scalarBarActor);
        renderer.addActor(actor);
        renderer.resetCamera();
        renderWindow.render();

        context.current = {
          fullScreenRenderer,
          renderWindow,
          renderer,
          actor,
          mapper,
          scalarBarActor,
        };
        setLoading(false);
      } catch (error) {
        if (!container) {
          return; // Abort if the container is not available
        }
        setLoading(false);
        navigate(DASHBOARD);
      }
    }
  };

  useEffect(() => {
    initializeVTK();

    return () => {
      if (context.current) {
        const { fullScreenRenderer, actor, mapper, scalarBarActor } =
          context.current;
        actor.delete();
        mapper.delete();
        scalarBarActor.delete();
        fullScreenRenderer.getInteractor().unbindEvents();
        fullScreenRenderer.delete();
        context.current = null;
      }
    };
  }, []);

  const handleRepresentationChange = (ev) => {
    const newRepresentation = Number(ev.target.value);
    setRepresentation(newRepresentation);
    if (context.current) {
      const { actor, renderWindow } = context.current;
      actor.getProperty().setRepresentation(newRepresentation);
      renderWindow.render();
    }
  };

After rendering this component, I encounter an issue when I navigate to another component or webpage and change my screen size. The error message is as follows:

“Cannot read properties of undefined (reading ‘getBoundingClientRect’)
TypeError: Cannot read properties of undefined (reading ‘getBoundingClientRect’)
at publicAPI.resize (http://localhost:3000/static/js/bundle.js:27458:34)”

Could anyone please help me resolve this issue?

This looks like a bug with the fullscreen renderer, where the resize event listener isn’t being cleaned up.

I would suggest using the vtkGenericRenderWindow class, but it looks like that also has the same bug. I’ll make a fix.

Thank you for your response and for identifying the issue. I appreciate your suggestion to use the vtkGenericRenderWindow class and your commitment to fixing the bug. Could you please give me an estimate of when I can expect this fix to be implemented? Thanks again for your help.

There’s this PR that should fix the issue: fix(GenericRenderWindow): remove event listeners by floryst · Pull Request #3091 · Kitware/vtk-js · GitHub

The above PR has been merged, and will be available shortly as a vtk.js release.

Thank you for your help