diff --git a/web/app/components/header/account-setting/data-source-page-new/hooks/__tests__/use-marketplace-all-plugins.spec.ts b/web/app/components/header/account-setting/data-source-page-new/hooks/__tests__/use-marketplace-all-plugins.spec.ts index 8e0dc0675d8..cae824f953e 100644 --- a/web/app/components/header/account-setting/data-source-page-new/hooks/__tests__/use-marketplace-all-plugins.spec.ts +++ b/web/app/components/header/account-setting/data-source-page-new/hooks/__tests__/use-marketplace-all-plugins.spec.ts @@ -25,7 +25,7 @@ vi.mock('@/app/components/plugins/marketplace/hooks', () => ({ describe('useMarketplaceAllPlugins', () => { const mockQueryPlugins = vi.fn() const mockQueryPluginsWithDebounced = vi.fn() - const mockResetPlugins = vi.fn() + const mockResetQueryParams = vi.fn() const mockCancelQueryPluginsWithDebounced = vi.fn() const mockFetchNextPage = vi.fn() @@ -35,7 +35,7 @@ describe('useMarketplaceAllPlugins', () => { ({ plugins: [], total: 0, - resetPlugins: mockResetPlugins, + resetQueryParams: mockResetQueryParams, queryPlugins: mockQueryPlugins, queryPluginsWithDebounced: mockQueryPluginsWithDebounced, cancelQueryPluginsWithDebounced: mockCancelQueryPluginsWithDebounced, diff --git a/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts b/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts index 918f4f75f6f..ca119d99e50 100644 --- a/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts +++ b/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts @@ -987,7 +987,7 @@ describe('hooks', () => { const queryPlugins = vi.fn() const queryPluginsWithDebounced = vi.fn() const cancelQueryPluginsWithDebounced = vi.fn() - const resetPlugins = vi.fn() + const resetQueryParams = vi.fn() ;(useMarketplacePluginsByCollectionId as Mock).mockReturnValue({ plugins: [{ plugin_id: 'collection-only', type: 'plugin' }], isLoading: true, @@ -997,7 +997,7 @@ describe('hooks', () => { queryPlugins, queryPluginsWithDebounced, cancelQueryPluginsWithDebounced, - resetPlugins, + resetQueryParams, isLoading: true, }) @@ -1007,8 +1007,8 @@ describe('hooks', () => { expect(queryPlugins).not.toHaveBeenCalled() expect(queryPluginsWithDebounced).not.toHaveBeenCalled() expect(cancelQueryPluginsWithDebounced).toHaveBeenCalled() - expect(resetPlugins).not.toHaveBeenCalled() expect(useMarketplacePlugins).toHaveBeenCalledWith(false) + expect(resetQueryParams).toHaveBeenCalled() expect(result.current.plugins).toEqual([]) expect(result.current.isLoading).toBe(false) }) diff --git a/web/app/components/header/account-setting/model-provider-page/hooks.ts b/web/app/components/header/account-setting/model-provider-page/hooks.ts index 5edc03781ec..1b3bec5336f 100644 --- a/web/app/components/header/account-setting/model-provider-page/hooks.ts +++ b/web/app/components/header/account-setting/model-provider-page/hooks.ts @@ -241,12 +241,14 @@ export const useMarketplaceAllPlugins = ( queryPlugins, queryPluginsWithDebounced, cancelQueryPluginsWithDebounced = () => {}, + resetQueryParams = () => {}, isLoading: isPluginsLoading, } = useMarketplacePlugins(enabled) useEffect(() => { if (!enabled) { cancelQueryPluginsWithDebounced() + resetQueryParams() return } @@ -275,6 +277,7 @@ export const useMarketplaceAllPlugins = ( enabled, queryPlugins, queryPluginsWithDebounced, + resetQueryParams, searchText, exclude, ]) diff --git a/web/app/components/plugins/marketplace/__tests__/hooks.spec.tsx b/web/app/components/plugins/marketplace/__tests__/hooks.spec.tsx index 46c770694b2..567f32f5b58 100644 --- a/web/app/components/plugins/marketplace/__tests__/hooks.spec.tsx +++ b/web/app/components/plugins/marketplace/__tests__/hooks.spec.tsx @@ -1,6 +1,8 @@ import type { ReactNode } from 'react' +import type { Plugin } from '@/app/components/plugins/types' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { act, renderHook, waitFor } from '@testing-library/react' +import { PluginCategoryEnum } from '@/app/components/plugins/types' const getMarketplacePluginsByCollectionId = vi.hoisted(() => vi.fn()) const getMarketplaceCollectionsAndPlugins = vi.hoisted(() => vi.fn()) @@ -149,3 +151,79 @@ describe('useMarketplaceCollectionsAndPlugins', () => { }) }) }) + +const createPlugin = (pluginID: string, category: PluginCategoryEnum) => + ({ + plugin_id: pluginID, + type: 'plugin', + category, + }) as Plugin + +const createInfiniteData = (plugin: Plugin, pageSize: number) => ({ + pages: [ + { + plugins: [plugin], + total: 1, + page: 1, + page_size: pageSize, + }, + ], + pageParams: [1], +}) + +const createWrapperWithQueryClient = (queryClient: QueryClient) => + function Wrapper({ children }: { children: ReactNode }) { + return {children} + } + +describe('useMarketplacePlugins', () => { + it('should reset local query params without removing marketplace plugin caches', async () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false, gcTime: Infinity }, + }, + }) + const toolPlugin = createPlugin('tool-plugin', PluginCategoryEnum.tool) + const modelPlugin = createPlugin('model-plugin', PluginCategoryEnum.model) + const toolParams = { + query: 'search', + category: PluginCategoryEnum.tool, + type: 'plugin' as const, + page_size: 40, + } + const modelParams = { + query: '', + category: PluginCategoryEnum.model, + type: 'plugin' as const, + page_size: 1000, + } + const toolQueryKey = ['marketplacePlugins', toolParams] + const modelQueryKey = ['marketplacePlugins', modelParams] + const toolQueryData = createInfiniteData(toolPlugin, toolParams.page_size) + const modelQueryData = createInfiniteData(modelPlugin, modelParams.page_size) + + queryClient.setQueryData(toolQueryKey, toolQueryData) + queryClient.setQueryData(modelQueryKey, modelQueryData) + + const { useMarketplacePlugins } = await import('../hooks') + const { result } = renderHook(() => useMarketplacePlugins(), { + wrapper: createWrapperWithQueryClient(queryClient), + }) + + act(() => { + result.current.queryPlugins(toolParams) + }) + + await waitFor(() => { + expect(result.current.plugins).toEqual([toolPlugin]) + }) + + act(() => { + result.current.resetQueryParams() + }) + + expect(result.current.plugins).toBeUndefined() + expect(queryClient.getQueryData(toolQueryKey)).toEqual(toolQueryData) + expect(queryClient.getQueryData(modelQueryKey)).toEqual(modelQueryData) + }) +}) diff --git a/web/app/components/plugins/marketplace/hooks.ts b/web/app/components/plugins/marketplace/hooks.ts index 455ae83dd92..78f8d19ccbe 100644 --- a/web/app/components/plugins/marketplace/hooks.ts +++ b/web/app/components/plugins/marketplace/hooks.ts @@ -5,7 +5,7 @@ import type { PluginsSearchParams, } from '@dify/contracts/marketplace' import type { Plugin } from '../types' -import { useInfiniteQuery, useQuery, useQueryClient } from '@tanstack/react-query' +import { useInfiniteQuery, useQuery } from '@tanstack/react-query' import { useDebounceFn } from 'ahooks' import { useCallback, useEffect, useState } from 'react' import { postMarketplace } from '@/service/base' @@ -81,7 +81,6 @@ export const useMarketplacePluginsByCollectionId = ( * @deprecated Use useMarketplacePlugins from query.ts instead */ export const useMarketplacePlugins = (enabled = true) => { - const queryClient = useQueryClient() const [queryParams, setQueryParams] = useState() const normalizeParams = useCallback((pluginsSearchParams: PluginsSearchParams) => { @@ -156,12 +155,9 @@ export const useMarketplacePlugins = (enabled = true) => { retry: false, }) - const resetPlugins = useCallback(() => { + const resetQueryParams = useCallback(() => { setQueryParams(undefined) - queryClient.removeQueries({ - queryKey: ['marketplacePlugins'], - }) - }, [queryClient]) + }, []) const handleUpdatePlugins = useCallback( (pluginsSearchParams: PluginsSearchParams) => { @@ -195,7 +191,7 @@ export const useMarketplacePlugins = (enabled = true) => { return { plugins, total, - resetPlugins, + resetQueryParams, queryPlugins: handleUpdatePlugins, queryPluginsWithDebounced, cancelQueryPluginsWithDebounced, diff --git a/web/app/components/tools/marketplace/__tests__/hooks.spec.ts b/web/app/components/tools/marketplace/__tests__/hooks.spec.ts index b78f59faa85..9420caa44e8 100644 --- a/web/app/components/tools/marketplace/__tests__/hooks.spec.ts +++ b/web/app/components/tools/marketplace/__tests__/hooks.spec.ts @@ -14,7 +14,7 @@ import { useMarketplace } from '../hooks' const mockQueryMarketplaceCollectionsAndPlugins = vi.fn() const mockQueryPlugins = vi.fn() const mockQueryPluginsWithDebounced = vi.fn() -const mockResetPlugins = vi.fn() +const mockResetQueryParams = vi.fn() const mockFetchNextPage = vi.fn() const mockUseMarketplaceCollectionsAndPlugins = vi.fn() @@ -70,7 +70,7 @@ const setupHookMocks = (overrides?: { }) mockUseMarketplacePlugins.mockReturnValue({ plugins: overrides?.plugins, - resetPlugins: mockResetPlugins, + resetQueryParams: mockResetQueryParams, queryPlugins: mockQueryPlugins, queryPluginsWithDebounced: mockQueryPluginsWithDebounced, isLoading: overrides?.isPluginsLoading ?? false, @@ -125,7 +125,7 @@ describe('useMarketplace', () => { }) expect(mockQueryPluginsWithDebounced).not.toHaveBeenCalled() expect(mockQueryMarketplaceCollectionsAndPlugins).not.toHaveBeenCalled() - expect(mockResetPlugins).not.toHaveBeenCalled() + expect(mockResetQueryParams).not.toHaveBeenCalled() }) it('should query plugins immediately when only tags are provided', async () => { @@ -163,7 +163,7 @@ describe('useMarketplace', () => { type: 'plugin', }) }) - expect(mockResetPlugins).toHaveBeenCalledTimes(1) + expect(mockResetQueryParams).toHaveBeenCalledTimes(1) }) }) diff --git a/web/app/components/tools/marketplace/hooks.ts b/web/app/components/tools/marketplace/hooks.ts index 1b692200c0b..2985e97dbc4 100644 --- a/web/app/components/tools/marketplace/hooks.ts +++ b/web/app/components/tools/marketplace/hooks.ts @@ -29,13 +29,13 @@ export const useMarketplace = ( } = useMarketplaceCollectionsAndPlugins() const { plugins, - resetPlugins, + resetQueryParams, queryPlugins, isLoading: isPluginsLoading, fetchNextPage, hasNextPage, page: pluginsPage, - } = useMarketplacePlugins() + } = useMarketplacePlugins(enabled) const searchPluginTextRef = useRef(searchPluginText) const filterPluginTagsRef = useRef(filterPluginTags) @@ -72,7 +72,7 @@ export const useMarketplace = ( exclude, type: 'plugin', }) - resetPlugins() + resetQueryParams() } } }, [ @@ -80,7 +80,7 @@ export const useMarketplace = ( filterPluginTags, queryPlugins, queryMarketplaceCollectionsAndPlugins, - resetPlugins, + resetQueryParams, exclude, enabled, isSuccess,