From 59f024dad35ff4d681ad11080d8db844f66f47e5 Mon Sep 17 00:00:00 2001 From: Vipin Chaudhary Date: Thu, 18 Dec 2025 18:44:16 +0530 Subject: [PATCH] [WIKI-849] feat: debounce for mention search (#8380) --- packages/editor/package.json | 2 ++ .../mentions/mentions-list-dropdown.tsx | 30 ++++++++++++++----- pnpm-lock.yaml | 6 ++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/packages/editor/package.json b/packages/editor/package.json index 0f3b13f50f..e981bfa3f6 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -62,6 +62,7 @@ "@tiptap/react": "^2.22.3", "@tiptap/starter-kit": "^2.22.3", "@tiptap/suggestion": "^2.22.3", + "lodash-es": "catalog:", "buffer": "^6.0.3", "emoji-regex": "^10.3.0", "highlight.js": "^11.8.0", @@ -85,6 +86,7 @@ "@types/node": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", + "@types/lodash-es": "catalog:", "postcss": "^8.4.38", "tsdown": "catalog:", "typescript": "catalog:" diff --git a/packages/editor/src/core/extensions/mentions/mentions-list-dropdown.tsx b/packages/editor/src/core/extensions/mentions/mentions-list-dropdown.tsx index d532290f21..e2b3ec7292 100644 --- a/packages/editor/src/core/extensions/mentions/mentions-list-dropdown.tsx +++ b/packages/editor/src/core/extensions/mentions/mentions-list-dropdown.tsx @@ -2,6 +2,7 @@ import { FloatingOverlay } from "@floating-ui/react"; import type { SuggestionProps } from "@tiptap/suggestion"; import { forwardRef, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react"; import { v4 as uuidv4 } from "uuid"; +import { debounce } from "lodash-es"; // plane utils import { useOutsideClickDetector } from "@plane/hooks"; import { cn } from "@plane/utils"; @@ -75,12 +76,12 @@ export const MentionsListDropdown = forwardRef(function MentionsListDropdown(pro }); }, [sections]); - // fetch mention sections based on query - useEffect(() => { - const fetchSuggestions = async () => { + // debounced search callback + const debouncedSearchCallback = useCallback( + debounce(async (searchQuery: string) => { setIsLoading(true); try { - const sectionsResponse = await searchCallback?.(query); + const sectionsResponse = await searchCallback?.(searchQuery); if (sectionsResponse) { setSections(sectionsResponse); } @@ -89,9 +90,24 @@ export const MentionsListDropdown = forwardRef(function MentionsListDropdown(pro } finally { setIsLoading(false); } - }; - fetchSuggestions(); - }, [query, searchCallback]); + }, 300), + [searchCallback] + ); + + // trigger debounced search when query changes + useEffect(() => { + if (query) { + void debouncedSearchCallback(query); + } + }, [query, debouncedSearchCallback]); + + // cancel pending debounced calls on unmount + useEffect( + () => () => { + debouncedSearchCallback.cancel(); + }, + [debouncedSearchCallback] + ); // scroll to the dropdown item when navigating via keyboard useLayoutEffect(() => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 231d572a05..95b477f47e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -950,6 +950,9 @@ importers: linkifyjs: specifier: ^4.3.2 version: 4.3.2 + lodash-es: + specifier: 'catalog:' + version: 4.17.21 lowlight: specifier: ^3.0.0 version: 3.3.0 @@ -993,6 +996,9 @@ importers: '@plane/typescript-config': specifier: workspace:* version: link:../typescript-config + '@types/lodash-es': + specifier: 'catalog:' + version: 4.17.12 '@types/node': specifier: 'catalog:' version: 22.12.0