Skip to content

Commit d4ee950

Browse files
fix(web): create custom hook for useRef logic (#666)
# Summary This PR removes duplicated `useRef` logic inside `EnrichedTextInput` by extracting it into a custom `useStableRef` hook. ## Test Plan Run the example web app and verify that all enriched editor functionalities work properly. ## Screenshots / Videos n/a ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ❌ | | Android | ❌ | | Web | ✅ | ## Checklist - [X] E2E tests are passing - [ ] Required E2E tests have been added (if applicable)
1 parent ffd9b39 commit d4ee950

2 files changed

Lines changed: 30 additions & 47 deletions

File tree

src/web/EnrichedTextInput.tsx

Lines changed: 18 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ import { StripMarksOnImagePlugin } from './pmPlugins/StripMarksOnImagePlugin';
7676
import { ShortcutPlugin } from './pmPlugins/ShortcutPlugin';
7777
import { returnKeyTypeToEnterKeyHint } from './returnKeyTypeToEnterKeyHint';
7878
import { AutolinkPlugin } from './pmPlugins/AutolinkPlugin';
79+
import { useStableRef } from './useStableRef';
7980

8081
function runFocused(
8182
editor: Editor,
@@ -126,56 +127,26 @@ export const EnrichedTextInput = ({
126127
() => mergeWithDefaultHtmlStyle(htmlStyle),
127128
[htmlStyle]
128129
);
129-
130-
const htmlStyleRef = useRef(resolvedHtmlStyle);
131-
useEffect(() => {
132-
htmlStyleRef.current = resolvedHtmlStyle;
133-
}, [resolvedHtmlStyle]);
134-
135-
const onPasteImagesRef = useRef(onPasteImages);
136-
useEffect(() => {
137-
onPasteImagesRef.current = onPasteImages;
138-
}, [onPasteImages]);
139-
140-
const mentionIndicatorsRef = useRef(mentionIndicators);
141-
useEffect(() => {
142-
mentionIndicatorsRef.current = mentionIndicators;
143-
}, [mentionIndicators]);
144-
145-
const mentionCallbacksRef = useRef({
146-
onStartMention,
147-
onChangeMention,
148-
onEndMention,
149-
onMentionDetected,
150-
});
151-
useEffect(() => {
152-
mentionCallbacksRef.current = {
130+
const mentionCallbacks = useMemo(
131+
() => ({
153132
onStartMention,
154133
onChangeMention,
155134
onEndMention,
156135
onMentionDetected,
157-
};
158-
}, [onStartMention, onChangeMention, onEndMention, onMentionDetected]);
159-
160-
const submitBehaviorRef = useRef(submitBehavior);
161-
const onSubmitEditingRef = useRef(onSubmitEditing);
162-
const onKeyPressRef = useRef(onKeyPress);
163-
const editorInstanceRef = useRef<Editor | null>(null);
136+
}),
137+
[onStartMention, onChangeMention, onEndMention, onMentionDetected]
138+
);
164139

165-
useEffect(() => {
166-
submitBehaviorRef.current = submitBehavior;
167-
}, [submitBehavior]);
168-
useEffect(() => {
169-
onSubmitEditingRef.current = onSubmitEditing;
170-
}, [onSubmitEditing]);
171-
useEffect(() => {
172-
onKeyPressRef.current = onKeyPress;
173-
}, [onKeyPress]);
140+
const htmlStyleRef = useStableRef(resolvedHtmlStyle);
141+
const onPasteImagesRef = useStableRef(onPasteImages);
142+
const mentionIndicatorsRef = useStableRef(mentionIndicators);
143+
const submitBehaviorRef = useStableRef(submitBehavior);
144+
const onSubmitEditingRef = useStableRef(onSubmitEditing);
145+
const onKeyPressRef = useStableRef(onKeyPress);
146+
const useHtmlNormalizerRef = useStableRef(useHtmlNormalizer);
147+
const mentionCallbacksRef = useStableRef(mentionCallbacks);
174148

175-
const useHtmlNormalizerRef = useRef(useHtmlNormalizer);
176-
useEffect(() => {
177-
useHtmlNormalizerRef.current = useHtmlNormalizer;
178-
}, [useHtmlNormalizer]);
149+
const editorInstanceRef = useRef<Editor | null>(null);
179150

180151
const handleKeyDown = (doc: Node, event: KeyboardEvent): boolean => {
181152
onKeyPressRef.current?.(adaptWebToNativeEvent(event, { key: event.key }));
@@ -252,7 +223,7 @@ export const EnrichedTextInput = ({
252223
showOnlyWhenEditable: true,
253224
}),
254225
],
255-
[placeholder]
226+
[placeholder, htmlStyleRef, mentionIndicatorsRef]
256227
);
257228

258229
const editor = useEditor(
@@ -324,7 +295,7 @@ export const EnrichedTextInput = ({
324295
useEffect(() => {
325296
if (!editor) return;
326297
return subscribeMentionEvents(editor, () => mentionCallbacksRef.current);
327-
}, [editor]);
298+
}, [editor, mentionCallbacksRef]);
328299

329300
useOnChangeHtml(editor, onChangeHtml);
330301
useOnChangeText(editor, onChangeText);
@@ -388,7 +359,7 @@ export const EnrichedTextInput = ({
388359
setNativeProps: () => {},
389360
setTextAlignment: () => {},
390361
}),
391-
[editor]
362+
[editor, mentionIndicatorsRef, useHtmlNormalizerRef]
392363
);
393364

394365
const editorStyle: CSSProperties = useMemo(

src/web/useStableRef.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useEffect, useRef, type RefObject } from 'react';
2+
3+
//TODO: When upgrading to React 19.2 migrate to useEffectEvent instead
4+
export const useStableRef = <T>(value: T): RefObject<T> => {
5+
const ref = useRef<T>(value);
6+
7+
useEffect(() => {
8+
ref.current = value;
9+
}, [value]);
10+
11+
return ref;
12+
};

0 commit comments

Comments
 (0)