mirror of https://github.com/langgenius/dify.git
refactor: move marketplace search to react-query
This commit is contained in:
parent
10d32beeb1
commit
e759243c84
|
|
@ -50,7 +50,7 @@ export type MarketplaceContextValue = {
|
|||
activePluginType: string
|
||||
handleActivePluginTypeChange: (type: string) => void
|
||||
page: number
|
||||
handlePageChange: (page: number) => void
|
||||
handlePageChange: () => void
|
||||
plugins?: Plugin[]
|
||||
pluginsTotal?: number
|
||||
resetPlugins: () => void
|
||||
|
|
@ -128,8 +128,6 @@ export const MarketplaceContextProvider = ({
|
|||
const filterPluginTagsRef = useRef(filterPluginTags)
|
||||
const [activePluginType, setActivePluginType] = useState(categoryFromSearchParams)
|
||||
const activePluginTypeRef = useRef(activePluginType)
|
||||
const [page, setPage] = useState(1)
|
||||
const pageRef = useRef(page)
|
||||
const [sort, setSort] = useState(DEFAULT_SORT)
|
||||
const sortRef = useRef(sort)
|
||||
const {
|
||||
|
|
@ -149,7 +147,11 @@ export const MarketplaceContextProvider = ({
|
|||
queryPluginsWithDebounced,
|
||||
cancelQueryPluginsWithDebounced,
|
||||
isLoading: isPluginsLoading,
|
||||
fetchNextPage: fetchNextPluginsPage,
|
||||
hasNextPage: hasNextPluginsPage,
|
||||
page: pluginsPage,
|
||||
} = useMarketplacePlugins()
|
||||
const page = Math.max(pluginsPage || 0, 1)
|
||||
|
||||
useEffect(() => {
|
||||
if (queryFromSearchParams || hasValidTags || hasValidCategory) {
|
||||
|
|
@ -160,7 +162,6 @@ export const MarketplaceContextProvider = ({
|
|||
sortBy: sortRef.current.sortBy,
|
||||
sortOrder: sortRef.current.sortOrder,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
const url = new URL(window.location.href)
|
||||
if (searchParams?.language)
|
||||
|
|
@ -221,7 +222,6 @@ export const MarketplaceContextProvider = ({
|
|||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}
|
||||
else {
|
||||
|
|
@ -233,7 +233,6 @@ export const MarketplaceContextProvider = ({
|
|||
sortOrder: sortRef.current.sortOrder,
|
||||
exclude,
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
}
|
||||
}, [exclude, queryPluginsWithDebounced, queryPlugins, handleUpdateSearchParams])
|
||||
|
|
@ -252,8 +251,6 @@ export const MarketplaceContextProvider = ({
|
|||
const handleSearchPluginTextChange = useCallback((text: string) => {
|
||||
setSearchPluginText(text)
|
||||
searchPluginTextRef.current = text
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
handleQuery(true)
|
||||
}, [handleQuery])
|
||||
|
|
@ -261,8 +258,6 @@ export const MarketplaceContextProvider = ({
|
|||
const handleFilterPluginTagsChange = useCallback((tags: string[]) => {
|
||||
setFilterPluginTags(tags)
|
||||
filterPluginTagsRef.current = tags
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
handleQuery()
|
||||
}, [handleQuery])
|
||||
|
|
@ -270,8 +265,6 @@ export const MarketplaceContextProvider = ({
|
|||
const handleActivePluginTypeChange = useCallback((type: string) => {
|
||||
setActivePluginType(type)
|
||||
activePluginTypeRef.current = type
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
handleQuery()
|
||||
}, [handleQuery])
|
||||
|
|
@ -279,20 +272,14 @@ export const MarketplaceContextProvider = ({
|
|||
const handleSortChange = useCallback((sort: PluginsSort) => {
|
||||
setSort(sort)
|
||||
sortRef.current = sort
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
handleQueryPlugins()
|
||||
}, [handleQueryPlugins])
|
||||
|
||||
const handlePageChange = useCallback(() => {
|
||||
if (pluginsTotal && plugins && pluginsTotal > plugins.length) {
|
||||
setPage(pageRef.current + 1)
|
||||
pageRef.current++
|
||||
|
||||
handleQueryPlugins()
|
||||
}
|
||||
}, [handleQueryPlugins, plugins, pluginsTotal])
|
||||
if (hasNextPluginsPage)
|
||||
fetchNextPluginsPage()
|
||||
}, [fetchNextPluginsPage, hasNextPluginsPage])
|
||||
|
||||
const handleMoreClick = useCallback((searchParams: SearchParamsFromCollection) => {
|
||||
setSearchPluginText(searchParams?.query || '')
|
||||
|
|
@ -305,9 +292,6 @@ export const MarketplaceContextProvider = ({
|
|||
sortBy: searchParams?.sort_by || DEFAULT_SORT.sortBy,
|
||||
sortOrder: searchParams?.sort_order || DEFAULT_SORT.sortOrder,
|
||||
}
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
handleQueryPlugins()
|
||||
}, [handleQueryPlugins])
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ import {
|
|||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDebounceFn } from 'ahooks'
|
||||
import type {
|
||||
|
|
@ -20,9 +24,8 @@ import {
|
|||
getMarketplacePluginsByCollectionId,
|
||||
} from './utils'
|
||||
import i18n from '@/i18n-config/i18next-config'
|
||||
import {
|
||||
useMutationPluginsFromMarketplace,
|
||||
} from '@/service/use-plugins'
|
||||
import { postMarketplace } from '@/service/base'
|
||||
import type { PluginsFromMarketplaceResponse } from '@/app/components/plugins/types'
|
||||
|
||||
export const useMarketplaceCollectionsAndPlugins = () => {
|
||||
const [queryParams, setQueryParams] = useState<CollectionsAndPluginsSearchParams>()
|
||||
|
|
@ -33,6 +36,7 @@ export const useMarketplaceCollectionsAndPlugins = () => {
|
|||
data,
|
||||
isFetching,
|
||||
isSuccess,
|
||||
isPending,
|
||||
} = useQuery({
|
||||
queryKey: ['marketplaceCollectionsAndPlugins', queryParams],
|
||||
queryFn: ({ signal }) => getMarketplaceCollectionsAndPlugins(queryParams, { signal }),
|
||||
|
|
@ -45,6 +49,7 @@ export const useMarketplaceCollectionsAndPlugins = () => {
|
|||
const queryMarketplaceCollectionsAndPlugins = useCallback((query?: CollectionsAndPluginsSearchParams) => {
|
||||
setQueryParams(query ? { ...query } : {})
|
||||
}, [])
|
||||
const isLoading = !!queryParams && (isFetching || isPending)
|
||||
|
||||
return {
|
||||
marketplaceCollections: marketplaceCollectionsOverride ?? data?.marketplaceCollections,
|
||||
|
|
@ -52,7 +57,7 @@ export const useMarketplaceCollectionsAndPlugins = () => {
|
|||
marketplaceCollectionPluginsMap: marketplaceCollectionPluginsMapOverride ?? data?.marketplaceCollectionPluginsMap,
|
||||
setMarketplaceCollectionPluginsMap,
|
||||
queryMarketplaceCollectionsAndPlugins,
|
||||
isLoading: isFetching,
|
||||
isLoading,
|
||||
isSuccess,
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +70,7 @@ export const useMarketplacePluginsByCollectionId = (
|
|||
data,
|
||||
isFetching,
|
||||
isSuccess,
|
||||
isPending,
|
||||
} = useQuery({
|
||||
queryKey: ['marketplaceCollectionPlugins', collectionId, query],
|
||||
queryFn: ({ signal }) => {
|
||||
|
|
@ -80,42 +86,104 @@ export const useMarketplacePluginsByCollectionId = (
|
|||
|
||||
return {
|
||||
plugins: data || [],
|
||||
isLoading: isFetching,
|
||||
isLoading: !!collectionId && (isFetching || isPending),
|
||||
isSuccess,
|
||||
}
|
||||
}
|
||||
|
||||
export const useMarketplacePlugins = () => {
|
||||
const {
|
||||
data,
|
||||
mutateAsync,
|
||||
reset,
|
||||
isPending,
|
||||
} = useMutationPluginsFromMarketplace()
|
||||
const queryClient = useQueryClient()
|
||||
const [queryParams, setQueryParams] = useState<PluginsSearchParams>()
|
||||
|
||||
const [prevPlugins, setPrevPlugins] = useState<Plugin[] | undefined>()
|
||||
const normalizeParams = useCallback((pluginsSearchParams: PluginsSearchParams) => {
|
||||
const pageSize = pluginsSearchParams.pageSize || 40
|
||||
|
||||
return {
|
||||
...pluginsSearchParams,
|
||||
pageSize,
|
||||
}
|
||||
}, [])
|
||||
|
||||
const marketplacePluginsQuery = useInfiniteQuery({
|
||||
queryKey: ['marketplacePlugins', queryParams],
|
||||
queryFn: async ({ pageParam = 1, signal }) => {
|
||||
if (!queryParams) {
|
||||
return {
|
||||
plugins: [] as Plugin[],
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 40,
|
||||
}
|
||||
}
|
||||
|
||||
const params = normalizeParams(queryParams)
|
||||
const {
|
||||
query,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
category,
|
||||
tags,
|
||||
exclude,
|
||||
type,
|
||||
pageSize,
|
||||
} = params
|
||||
const pluginOrBundle = type === 'bundle' ? 'bundles' : 'plugins'
|
||||
|
||||
try {
|
||||
const res = await postMarketplace<{ data: PluginsFromMarketplaceResponse }>(`/${pluginOrBundle}/search/advanced`, {
|
||||
body: {
|
||||
page: pageParam,
|
||||
page_size: pageSize,
|
||||
query,
|
||||
sort_by: sortBy,
|
||||
sort_order: sortOrder,
|
||||
category: category !== 'all' ? category : '',
|
||||
tags,
|
||||
exclude,
|
||||
type,
|
||||
},
|
||||
signal,
|
||||
})
|
||||
const resPlugins = res.data.bundles || res.data.plugins || []
|
||||
|
||||
return {
|
||||
plugins: resPlugins.map(plugin => getFormattedPlugin(plugin)),
|
||||
total: res.data.total,
|
||||
page: pageParam,
|
||||
pageSize,
|
||||
}
|
||||
}
|
||||
catch {
|
||||
return {
|
||||
plugins: [],
|
||||
total: 0,
|
||||
page: pageParam,
|
||||
pageSize,
|
||||
}
|
||||
}
|
||||
},
|
||||
getNextPageParam: (lastPage) => {
|
||||
const nextPage = lastPage.page + 1
|
||||
const loaded = lastPage.page * lastPage.pageSize
|
||||
return loaded < (lastPage.total || 0) ? nextPage : undefined
|
||||
},
|
||||
initialPageParam: 1,
|
||||
enabled: !!queryParams,
|
||||
staleTime: 1000 * 60 * 5,
|
||||
gcTime: 1000 * 60 * 10,
|
||||
retry: false,
|
||||
})
|
||||
|
||||
const resetPlugins = useCallback(() => {
|
||||
reset()
|
||||
setPrevPlugins(undefined)
|
||||
}, [reset])
|
||||
setQueryParams(undefined)
|
||||
queryClient.removeQueries({
|
||||
queryKey: ['marketplacePlugins'],
|
||||
})
|
||||
}, [queryClient])
|
||||
|
||||
const handleUpdatePlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => {
|
||||
mutateAsync(pluginsSearchParams).then((res) => {
|
||||
const currentPage = pluginsSearchParams.page || 1
|
||||
const resPlugins = res.data.bundles || res.data.plugins
|
||||
if (currentPage > 1) {
|
||||
setPrevPlugins(prevPlugins => [...(prevPlugins || []), ...resPlugins.map((plugin) => {
|
||||
return getFormattedPlugin(plugin)
|
||||
})])
|
||||
}
|
||||
else {
|
||||
setPrevPlugins(resPlugins.map((plugin) => {
|
||||
return getFormattedPlugin(plugin)
|
||||
}))
|
||||
}
|
||||
})
|
||||
}, [mutateAsync])
|
||||
setQueryParams(normalizeParams(pluginsSearchParams))
|
||||
}, [normalizeParams])
|
||||
|
||||
const { run: queryPluginsWithDebounced, cancel: cancelQueryPluginsWithDebounced } = useDebounceFn((pluginsSearchParams: PluginsSearchParams) => {
|
||||
handleUpdatePlugins(pluginsSearchParams)
|
||||
|
|
@ -123,14 +191,29 @@ export const useMarketplacePlugins = () => {
|
|||
wait: 500,
|
||||
})
|
||||
|
||||
const hasQuery = !!queryParams
|
||||
const hasData = marketplacePluginsQuery.data !== undefined
|
||||
const plugins = hasQuery && hasData
|
||||
? marketplacePluginsQuery.data.pages.flatMap(page => page.plugins)
|
||||
: undefined
|
||||
const total = hasQuery && hasData ? marketplacePluginsQuery.data.pages?.[0]?.total : undefined
|
||||
const isPluginsLoading = hasQuery && (
|
||||
marketplacePluginsQuery.isPending
|
||||
|| (marketplacePluginsQuery.isFetching && !marketplacePluginsQuery.data)
|
||||
)
|
||||
|
||||
return {
|
||||
plugins: prevPlugins,
|
||||
total: data?.data?.total,
|
||||
plugins,
|
||||
total,
|
||||
resetPlugins,
|
||||
queryPlugins: handleUpdatePlugins,
|
||||
queryPluginsWithDebounced,
|
||||
cancelQueryPluginsWithDebounced,
|
||||
isLoading: isPending,
|
||||
isLoading: isPluginsLoading,
|
||||
isFetchingNextPage: marketplacePluginsQuery.isFetchingNextPage,
|
||||
hasNextPage: marketplacePluginsQuery.hasNextPage,
|
||||
fetchNextPage: marketplacePluginsQuery.fetchNextPage,
|
||||
page: marketplacePluginsQuery.data?.pages?.length || (marketplacePluginsQuery.isPending && hasQuery ? 1 : 0),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import {
|
|||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import {
|
||||
useMarketplaceCollectionsAndPlugins,
|
||||
|
|
@ -31,10 +30,10 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
|
|||
queryPlugins,
|
||||
queryPluginsWithDebounced,
|
||||
isLoading: isPluginsLoading,
|
||||
total: pluginsTotal,
|
||||
fetchNextPage,
|
||||
hasNextPage,
|
||||
page: pluginsPage,
|
||||
} = useMarketplacePlugins()
|
||||
const [page, setPage] = useState(1)
|
||||
const pageRef = useRef(page)
|
||||
const searchPluginTextRef = useRef(searchPluginText)
|
||||
const filterPluginTagsRef = useRef(filterPluginTags)
|
||||
|
||||
|
|
@ -44,9 +43,6 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
|
|||
}, [searchPluginText, filterPluginTags])
|
||||
useEffect(() => {
|
||||
if ((searchPluginText || filterPluginTags.length) && isSuccess) {
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
|
||||
if (searchPluginText) {
|
||||
queryPluginsWithDebounced({
|
||||
category: PluginCategoryEnum.tool,
|
||||
|
|
@ -54,7 +50,6 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
|
|||
tags: filterPluginTags,
|
||||
exclude,
|
||||
type: 'plugin',
|
||||
page: pageRef.current,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
|
@ -64,7 +59,6 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
|
|||
tags: filterPluginTags,
|
||||
exclude,
|
||||
type: 'plugin',
|
||||
page: pageRef.current,
|
||||
})
|
||||
}
|
||||
else {
|
||||
|
|
@ -90,21 +84,10 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
|
|||
if (scrollTop + clientHeight >= scrollHeight - 5 && scrollTop > 0) {
|
||||
const searchPluginText = searchPluginTextRef.current
|
||||
const filterPluginTags = filterPluginTagsRef.current
|
||||
if (pluginsTotal && plugins && pluginsTotal > plugins.length && (!!searchPluginText || !!filterPluginTags.length)) {
|
||||
setPage(pageRef.current + 1)
|
||||
pageRef.current++
|
||||
|
||||
queryPlugins({
|
||||
category: PluginCategoryEnum.tool,
|
||||
query: searchPluginText,
|
||||
tags: filterPluginTags,
|
||||
exclude,
|
||||
type: 'plugin',
|
||||
page: pageRef.current,
|
||||
})
|
||||
}
|
||||
if (hasNextPage && (!!searchPluginText || !!filterPluginTags.length))
|
||||
fetchNextPage()
|
||||
}
|
||||
}, [exclude, plugins, pluginsTotal, queryPlugins])
|
||||
}, [exclude, fetchNextPage, hasNextPage, plugins, queryPlugins])
|
||||
|
||||
return {
|
||||
isLoading: isLoading || isPluginsLoading,
|
||||
|
|
@ -112,6 +95,6 @@ export const useMarketplace = (searchPluginText: string, filterPluginTags: strin
|
|||
marketplaceCollectionPluginsMap,
|
||||
plugins,
|
||||
handleScroll,
|
||||
page,
|
||||
page: Math.max(pluginsPage || 0, 1),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue