fix: 移除对 @tanstack/react-query 的依赖,使用项目现有 hooks 模式
项目未安装 @tanstack/react-query,将 useWorksSearch hook 改为使用项目现有的模式: - 使用 useState 管理状态 - 使用 useCallback 封装逻辑 - 使用 useEffect 自动执行搜索 - 使用 handleError 统一错误处理 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e1340fa101
commit
7d160d55ea
|
|
@ -2,17 +2,19 @@
|
||||||
* TDD Phase 2: GREEN - Minimal code to pass tests
|
* TDD Phase 2: GREEN - Minimal code to pass tests
|
||||||
*
|
*
|
||||||
* This Hook implements works search functionality:
|
* This Hook implements works search functionality:
|
||||||
* - Uses @tanstack/react-query for data fetching
|
|
||||||
* - Supports keyword search
|
* - Supports keyword search
|
||||||
* - Supports category filter
|
* - Supports category filter
|
||||||
* - Supports pagination
|
* - Supports pagination
|
||||||
* - Only executes query when keyword is provided
|
* - Only executes query when keyword is provided
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query'
|
|
||||||
import { root } from '@repo/core'
|
import { root } from '@repo/core'
|
||||||
import { TemplateGenerationController } from '@repo/sdk'
|
import { TemplateGenerationController } from '@repo/sdk'
|
||||||
import { useCallback } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
import { type ApiError } from '@/lib/types'
|
||||||
|
|
||||||
|
import { handleError } from './use-error'
|
||||||
|
|
||||||
// Type definitions
|
// Type definitions
|
||||||
export interface UseWorksSearchParams {
|
export interface UseWorksSearchParams {
|
||||||
|
|
@ -45,7 +47,7 @@ export interface WorksSearchResponse {
|
||||||
* Hook for searching works with keyword and category filtering
|
* Hook for searching works with keyword and category filtering
|
||||||
*
|
*
|
||||||
* @param params - Search parameters including keyword, category, page, and limit
|
* @param params - Search parameters including keyword, category, page, and limit
|
||||||
* @returns Query result with data, loading state, error, and refetch function
|
* @returns Object with data, loading state, error, and refetch function
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```tsx
|
* ```tsx
|
||||||
|
|
@ -58,47 +60,62 @@ export interface WorksSearchResponse {
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function useWorksSearch(params: UseWorksSearchParams) {
|
export function useWorksSearch(params: UseWorksSearchParams) {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [error, setError] = useState<ApiError | null>(null)
|
||||||
|
const [data, setData] = useState<WorksSearchResponse | undefined>(undefined)
|
||||||
|
|
||||||
const { keyword, category, page = 1, limit = 20 } = params
|
const { keyword, category, page = 1, limit = 20 } = params
|
||||||
|
|
||||||
// Build query key - "全部" category should not be included
|
const execute = useCallback(async () => {
|
||||||
const queryKey = [
|
// Only execute query when keyword has content
|
||||||
'worksSearch',
|
const trimmedKeyword = keyword?.trim() || ''
|
||||||
keyword,
|
if (!trimmedKeyword) {
|
||||||
category === '全部' ? undefined : category,
|
setData(undefined)
|
||||||
page,
|
setError(null)
|
||||||
limit,
|
return { data: undefined, error: null }
|
||||||
] as const
|
}
|
||||||
|
|
||||||
// Build API params - only include category if it's not "全部"
|
setLoading(true)
|
||||||
const apiParams = {
|
setError(null)
|
||||||
keyword,
|
|
||||||
...(category && category !== '全部' && { category }),
|
|
||||||
page,
|
|
||||||
limit,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query function
|
// Build API params - only include category if it's not "全部"
|
||||||
const queryFn = useCallback(async (): Promise<WorksSearchResponse> => {
|
const apiParams = {
|
||||||
const controller = root.get(TemplateGenerationController)
|
keyword: trimmedKeyword,
|
||||||
const result = await controller.list(apiParams)
|
...(category && category !== '全部' && { category }),
|
||||||
return result as WorksSearchResponse
|
page,
|
||||||
|
limit,
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateGeneration = root.get(TemplateGenerationController)
|
||||||
|
const { data: result, error: err } = await handleError(async () =>
|
||||||
|
await templateGeneration.list(apiParams)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
setError(err)
|
||||||
|
setLoading(false)
|
||||||
|
return { data: undefined, error: err }
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(result as WorksSearchResponse)
|
||||||
|
setLoading(false)
|
||||||
|
return { data: result as WorksSearchResponse, error: null }
|
||||||
}, [keyword, category, page, limit])
|
}, [keyword, category, page, limit])
|
||||||
|
|
||||||
// Execute query only when keyword has content
|
// Auto-execute search when params change
|
||||||
const trimmedKeyword = keyword?.trim() || ''
|
useEffect(() => {
|
||||||
const isEnabled = !!trimmedKeyword
|
execute()
|
||||||
|
}, [execute])
|
||||||
|
|
||||||
const query = useQuery({
|
const refetch = useCallback(() => {
|
||||||
queryKey,
|
return execute()
|
||||||
queryFn,
|
}, [execute])
|
||||||
enabled: isEnabled,
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: query.data,
|
data,
|
||||||
works: query.data?.data || [],
|
works: data?.data || [],
|
||||||
isLoading: query.isLoading,
|
isLoading: loading,
|
||||||
error: query.error,
|
error,
|
||||||
refetch: query.refetch,
|
refetch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue