From b1d982b98803719854d5a9a7d12ba0a35eb95f54 Mon Sep 17 00:00:00 2001 From: dwelle Date: Sun, 6 Aug 2023 21:41:37 +0200 Subject: [PATCH] remove throttling react 17 hack & disable on < 18 --- src/components/App.tsx | 5 --- src/components/canvases/InteractiveCanvas.tsx | 13 ++++---- src/components/canvases/StaticCanvas.tsx | 9 ++--- src/global.d.ts | 1 - src/utils.ts | 33 +++++++++++++++++++ 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index aed901743..23c26bdc5 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -351,10 +351,6 @@ import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; import { StaticCanvas, InteractiveCanvas } from "./canvases"; import { Renderer } from "../scene/Renderer"; -// remove this hack when we can sync render & resizeObserver (state update) -// to rAF. See #5439 -window.EXCALIDRAW_THROTTLE_NEXT_RENDER = true; - const AppContext = React.createContext(null!); const AppPropsContext = React.createContext(null!); @@ -1650,7 +1646,6 @@ class App extends React.Component { if ("ResizeObserver" in window && this.excalidrawContainerRef?.current) { this.resizeObserver = new ResizeObserver(() => { - window.EXCALIDRAW_THROTTLE_NEXT_RENDER = false; // recompute device dimensions state // --------------------------------------------------------------------- this.refreshDeviceState(this.excalidrawContainerRef.current!); diff --git a/src/components/canvases/InteractiveCanvas.tsx b/src/components/canvases/InteractiveCanvas.tsx index fdb641a62..4dcef0f52 100644 --- a/src/components/canvases/InteractiveCanvas.tsx +++ b/src/components/canvases/InteractiveCanvas.tsx @@ -1,6 +1,10 @@ import React, { useEffect, useRef } from "react"; import { renderInteractiveScene } from "../../renderer/renderScene"; -import { isShallowEqual, sceneCoordsToViewportCoords } from "../../utils"; +import { + isRenderThrottlingEnabled, + isShallowEqual, + sceneCoordsToViewportCoords, +} from "../../utils"; import { CURSOR_TYPE } from "../../constants"; import { t } from "../../i18n"; import type { DOMAttributes } from "react"; @@ -101,13 +105,8 @@ const InteractiveCanvas = (props: InteractiveCanvasProps) => { }, callback: props.renderInteractiveSceneCallback, }, - window.EXCALIDRAW_THROTTLE_NEXT_RENDER && - window.EXCALIDRAW_THROTTLE_RENDER === true, + isRenderThrottlingEnabled(), ); - - if (!window.EXCALIDRAW_THROTTLE_NEXT_RENDER) { - window.EXCALIDRAW_THROTTLE_NEXT_RENDER = true; - } }); return ( diff --git a/src/components/canvases/StaticCanvas.tsx b/src/components/canvases/StaticCanvas.tsx index fffd03cf0..24f44ae37 100644 --- a/src/components/canvases/StaticCanvas.tsx +++ b/src/components/canvases/StaticCanvas.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef } from "react"; import { RoughCanvas } from "roughjs/bin/canvas"; import { renderStaticScene } from "../../renderer/renderScene"; -import { isShallowEqual } from "../../utils"; +import { isRenderThrottlingEnabled, isShallowEqual } from "../../utils"; import type { AppState, StaticCanvasAppState } from "../../types"; import type { StaticCanvasRenderConfig } from "../../scene/types"; import type { NonDeletedExcalidrawElement } from "../../element/types"; @@ -37,13 +37,8 @@ const StaticCanvas = (props: StaticCanvasProps) => { appState: props.appState, renderConfig: props.renderConfig, }, - window.EXCALIDRAW_THROTTLE_NEXT_RENDER && - window.EXCALIDRAW_THROTTLE_RENDER === true, + isRenderThrottlingEnabled(), ); - - if (!window.EXCALIDRAW_THROTTLE_NEXT_RENDER) { - window.EXCALIDRAW_THROTTLE_NEXT_RENDER = true; - } }); return ( diff --git a/src/global.d.ts b/src/global.d.ts index e66929c54..76730c8de 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -17,7 +17,6 @@ interface Window { EXCALIDRAW_ASSET_PATH: string | undefined; EXCALIDRAW_EXPORT_SOURCE: string; EXCALIDRAW_THROTTLE_RENDER: boolean | undefined; - EXCALIDRAW_THROTTLE_NEXT_RENDER: boolean; gtag: Function; sa_event: Function; fathom: { trackEvent: Function }; diff --git a/src/utils.ts b/src/utils.ts index 1b4e6ea21..05f2e725c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -20,6 +20,7 @@ import { unstable_batchedUpdates } from "react-dom"; import { SHAPES } from "./shapes"; import { isEraserActive, isHandToolActive } from "./appState"; import { ResolutionType } from "./utility-types"; +import React from "react"; let mockDateTime: string | null = null; @@ -958,3 +959,35 @@ export const memoize = , R extends any>( return ret as typeof func & { clear: () => void }; }; + +export const isRenderThrottlingEnabled = (() => { + // we don't want to throttle in react < 18 because of #5439 and it was + // getting more complex to maintain the fix + let IS_REACT_18_AND_UP: boolean; + try { + const version = React.version.split("."); + IS_REACT_18_AND_UP = Number(version[0]) > 17; + } catch { + IS_REACT_18_AND_UP = false; + } + + IS_REACT_18_AND_UP = false; + + let hasWarned = false; + + return () => { + if (window.EXCALIDRAW_THROTTLE_RENDER === true) { + if (!IS_REACT_18_AND_UP) { + if (!hasWarned) { + hasWarned = true; + console.warn( + "Excalidraw: render throttling is disabled on React versions < 18.", + ); + } + return false; + } + return true; + } + return false; + }; +})();