From 51d1d121568b2bd1d5a7e2a734154e3f2c0311b3 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Wed, 7 Feb 2024 12:45:19 +0100 Subject: [PATCH] [CodeEditor] Explicitly call the latest `props.onChange` (#176296) ## Summary fix https://github.com/elastic/kibana/issues/175684 Refer to the issue https://github.com/elastic/kibana/issues/175684 for the problem and reproduction I tested that this fixes the issue using the story from the reproduction https://github.com/elastic/kibana/pull/175670 and the URL drilldown's placeholder issue explained in https://github.com/elastic/kibana/issues/175684 --- .../code_editor/impl/code_editor.tsx | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/shared-ux/code_editor/impl/code_editor.tsx b/packages/shared-ux/code_editor/impl/code_editor.tsx index 54be81c2df4b5..286c3af06e0b2 100644 --- a/packages/shared-ux/code_editor/impl/code_editor.tsx +++ b/packages/shared-ux/code_editor/impl/code_editor.tsx @@ -153,7 +153,7 @@ export interface CodeEditorProps { export const CodeEditor: React.FC = ({ languageId, value, - onChange, + onChange: _onChange, width, height, options, @@ -206,6 +206,8 @@ export const CodeEditor: React.FC = ({ const [isHintActive, setIsHintActive] = useState(true); + const onChange = useBug175684OnChange(_onChange); + const startEditing = useCallback(() => { setIsHintActive(false); _editor?.focus(); @@ -676,3 +678,20 @@ const useFitToContent = ({ }; }, [editor, isFitToContent, minLines, maxLines, isFullScreen]); }; + +// https://github.com/elastic/kibana/issues/175684 +// 'react-monaco-editor' has a bug that it always calls the initial onChange callback, so the closure might become stale +// we work this around by calling the latest onChange from props +const useBug175684OnChange = (onChange: CodeEditorProps['onChange']) => { + const onChangePropRef = useRef(onChange); + useEffect(() => { + onChangePropRef.current = onChange; + }, [onChange]); + const onChangeWrapper = useCallback>((_value, event) => { + if (onChangePropRef.current) { + onChangePropRef.current(_value, event); + } + }, []); + + return onChangeWrapper; +};