Skip to content

Commit dd886d0

Browse files
authored
add memoization in suggestion menu (#796)
1 parent 7593ba3 commit dd886d0

File tree

1 file changed

+31
-23
lines changed

1 file changed

+31
-23
lines changed

packages/react/src/components/SuggestionMenu/SuggestionMenuController.tsx

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
filterSuggestionItems,
77
} from "@blocknote/core";
88
import { flip, offset, size } from "@floating-ui/react";
9-
import { FC } from "react";
9+
import { FC, useCallback, useMemo } from "react";
1010

1111
import { useBlockNoteEditor } from "../../hooks/useBlockNoteEditor";
1212
import { useUIElementPositioning } from "../../hooks/useUIElementPositioning";
@@ -55,26 +55,42 @@ export function SuggestionMenuController<
5555

5656
const { triggerCharacter, suggestionMenuComponent } = props;
5757

58-
let { onItemClick, getItems } = props;
58+
const { onItemClick, getItems } = props;
5959

60-
if (!onItemClick) {
61-
onItemClick = (item: ItemType<GetItemsType>) => {
62-
item.onItemClick(editor);
63-
};
64-
}
60+
const onItemClickOrDefault = useMemo(() => {
61+
return (
62+
onItemClick ||
63+
((item: ItemType<GetItemsType>) => {
64+
item.onItemClick(editor);
65+
})
66+
);
67+
}, [editor, onItemClick]);
68+
69+
const getItemsOrDefault = useMemo(() => {
70+
return (
71+
getItems ||
72+
((async (query: string) =>
73+
filterSuggestionItems(
74+
getDefaultReactSlashMenuItems(editor),
75+
query
76+
)) as any as typeof getItems)
77+
);
78+
}, [editor, getItems])!;
6579

6680
const callbacks = {
6781
closeMenu: editor.suggestionMenus.closeMenu,
6882
clearQuery: editor.suggestionMenus.clearQuery,
6983
};
7084

71-
const state = useUIPluginState(
72-
(callback: (state: SuggestionMenuState) => void) =>
73-
editor.suggestionMenus.onUpdate.bind(editor.suggestionMenus)(
74-
triggerCharacter,
75-
callback
76-
)
85+
const cb = useCallback(
86+
(callback: (state: SuggestionMenuState) => void) => {
87+
return editor.suggestionMenus.onUpdate(triggerCharacter, callback);
88+
},
89+
[editor.suggestionMenus, triggerCharacter]
7790
);
91+
92+
const state = useUIPluginState(cb);
93+
7894
const { isMounted, ref, style, getFloatingProps } = useUIElementPositioning(
7995
state?.show || false,
8096
state?.referencePos || null,
@@ -106,23 +122,15 @@ export function SuggestionMenuController<
106122
return null;
107123
}
108124

109-
if (!getItems) {
110-
getItems = (async (query: string) =>
111-
filterSuggestionItems(
112-
getDefaultReactSlashMenuItems(editor),
113-
query
114-
)) as any;
115-
}
116-
117125
return (
118126
<div ref={ref} style={style} {...getFloatingProps()}>
119127
<SuggestionMenuWrapper
120128
query={state.query}
121129
closeMenu={callbacks.closeMenu}
122130
clearQuery={callbacks.clearQuery}
123-
getItems={getItems!}
131+
getItems={getItemsOrDefault}
124132
suggestionMenuComponent={suggestionMenuComponent || SuggestionMenu}
125-
onItemClick={onItemClick}
133+
onItemClick={onItemClickOrDefault}
126134
/>
127135
</div>
128136
);

0 commit comments

Comments
 (0)