@@ -2,6 +2,7 @@ import { FloatingOverlay } from "@floating-ui/react";
22import type { SuggestionProps } from "@tiptap/suggestion" ;
33import { forwardRef , useCallback , useEffect , useImperativeHandle , useLayoutEffect , useRef , useState } from "react" ;
44import { v4 as uuidv4 } from "uuid" ;
5+ import { debounce } from "lodash-es" ;
56// plane utils
67import { useOutsideClickDetector } from "@plane/hooks" ;
78import { cn } from "@plane/utils" ;
@@ -75,12 +76,12 @@ export const MentionsListDropdown = forwardRef(function MentionsListDropdown(pro
7576 } ) ;
7677 } , [ sections ] ) ;
7778
78- // fetch mention sections based on query
79- useEffect ( ( ) => {
80- const fetchSuggestions = async ( ) => {
79+ // debounced search callback
80+ const debouncedSearchCallback = useCallback (
81+ debounce ( async ( searchQuery : string ) => {
8182 setIsLoading ( true ) ;
8283 try {
83- const sectionsResponse = await searchCallback ?.( query ) ;
84+ const sectionsResponse = await searchCallback ?.( searchQuery ) ;
8485 if ( sectionsResponse ) {
8586 setSections ( sectionsResponse ) ;
8687 }
@@ -89,9 +90,24 @@ export const MentionsListDropdown = forwardRef(function MentionsListDropdown(pro
8990 } finally {
9091 setIsLoading ( false ) ;
9192 }
92- } ;
93- fetchSuggestions ( ) ;
94- } , [ query , searchCallback ] ) ;
93+ } , 300 ) ,
94+ [ searchCallback ]
95+ ) ;
96+
97+ // trigger debounced search when query changes
98+ useEffect ( ( ) => {
99+ if ( query ) {
100+ void debouncedSearchCallback ( query ) ;
101+ }
102+ } , [ query , debouncedSearchCallback ] ) ;
103+
104+ // cancel pending debounced calls on unmount
105+ useEffect (
106+ ( ) => ( ) => {
107+ debouncedSearchCallback . cancel ( ) ;
108+ } ,
109+ [ debouncedSearchCallback ]
110+ ) ;
95111
96112 // scroll to the dropdown item when navigating via keyboard
97113 useLayoutEffect ( ( ) => {
0 commit comments