From 5e7b6a8c750006568d3c2be9ea92d3b46a868d0d Mon Sep 17 00:00:00 2001 From: Sychev Andrey Date: Thu, 4 Jun 2026 11:50:44 +0200 Subject: [PATCH 1/2] dbeaver/pro#8333 fix: Eliminate React 19 error in useEditorDefaultExtensions replace useRef with useState for managing editor options state --- .../src/useEditorDefaultExtensions.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts b/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts index a48b3e3a416..6b8516feeed 100644 --- a/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts +++ b/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts @@ -22,7 +22,7 @@ import { tooltips, } from '@codemirror/view'; import { classHighlighter } from '@lezer/highlight'; -import { useRef } from 'react'; +import { useState } from 'react'; import { GlobalConstants, isObjectsEqual } from '@cloudbeaver/core-utils'; import { clsx } from '@dbeaver/ui-kit'; @@ -119,16 +119,18 @@ const DEFAULT_EXTENSIONS_COMPARTMENT = new Compartment(); /** Provides the necessary extensions to establish a basic editor */ export function useEditorDefaultExtensions(options?: IDefaultExtensions): [Compartment, Extension] { - const previousOptions = useRef(options); - const isOptionsChanged = !isObjectsEqual(options, previousOptions.current); - const extensions = useRef<[Compartment, Extension] | null>(null); + const [state, setState] = useState<{ options: IDefaultExtensions | undefined; result: [Compartment, Extension] }>(() => ({ + options, + result: createExtensions(options), + })); - if (isOptionsChanged || extensions.current === null) { - previousOptions.current = options; - extensions.current = createExtensions(options); + if (!isObjectsEqual(options, state.options)) { + const result = createExtensions(options); + setState({ options, result }); + return result; } - return extensions.current; + return state.result; } function createExtensions(options?: IDefaultExtensions): [Compartment, Extension] { From 7214ec2a724027b5d3e7ea5eb2b9ae8845696980 Mon Sep 17 00:00:00 2001 From: Sychev Andrey Date: Thu, 18 Jun 2026 11:41:18 +0200 Subject: [PATCH 2/2] dbeaver/pro#8333 refactor: memoize default editor extensions with useMemo --- .../src/useEditorDefaultExtensions.ts | 75 +++++++++++++++---- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts b/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts index 6b8516feeed..beeb580fefe 100644 --- a/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts +++ b/webapp/packages/plugin-codemirror6/src/useEditorDefaultExtensions.ts @@ -22,9 +22,9 @@ import { tooltips, } from '@codemirror/view'; import { classHighlighter } from '@lezer/highlight'; -import { useState } from 'react'; +import { useMemo } from 'react'; -import { GlobalConstants, isObjectsEqual } from '@cloudbeaver/core-utils'; +import { GlobalConstants } from '@cloudbeaver/core-utils'; import { clsx } from '@dbeaver/ui-kit'; // @TODO allow to configure bindings outside of the component @@ -119,18 +119,67 @@ const DEFAULT_EXTENSIONS_COMPARTMENT = new Compartment(); /** Provides the necessary extensions to establish a basic editor */ export function useEditorDefaultExtensions(options?: IDefaultExtensions): [Compartment, Extension] { - const [state, setState] = useState<{ options: IDefaultExtensions | undefined; result: [Compartment, Extension] }>(() => ({ - options, - result: createExtensions(options), - })); + const { + lineNumbers, + tooltips, + highlightSpecialChars, + syntaxHighlighting, + bracketMatching, + dropCursor, + crosshairCursor, + foldGutter, + highlightActiveLineGutter, + highlightSelectionMatches, + highlightActiveLine, + indentOnInput, + rectangularSelection, + keymap, + lineWrapping, + search, + tabIndentation, + } = options ?? {}; - if (!isObjectsEqual(options, state.options)) { - const result = createExtensions(options); - setState({ options, result }); - return result; - } - - return state.result; + return useMemo( + () => + createExtensions({ + lineNumbers, + tooltips, + highlightSpecialChars, + syntaxHighlighting, + bracketMatching, + dropCursor, + crosshairCursor, + foldGutter, + highlightActiveLineGutter, + highlightSelectionMatches, + highlightActiveLine, + indentOnInput, + rectangularSelection, + keymap, + lineWrapping, + search, + tabIndentation, + }), + [ + lineNumbers, + tooltips, + highlightSpecialChars, + syntaxHighlighting, + bracketMatching, + dropCursor, + crosshairCursor, + foldGutter, + highlightActiveLineGutter, + highlightSelectionMatches, + highlightActiveLine, + indentOnInput, + rectangularSelection, + keymap, + lineWrapping, + search, + tabIndentation, + ], + ); } function createExtensions(options?: IDefaultExtensions): [Compartment, Extension] {