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:
imeepos 2026-01-23 19:26:24 +08:00
parent e1340fa101
commit 7d160d55ea
1 changed files with 54 additions and 37 deletions

View File

@ -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,
} }
} }