You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TanStack Query v5自定义搜索Hook:如何使返回数据类型仅为T

解决data类型为T的方法

方法1:使用throwOnError + 类型断言

通过配置throwOnError: true让请求失败时自动抛出错误,结合类型断言确保data类型为T,同时处理加载状态避免初始崩溃:

import { useState } from "react"
import { useQuery } from "@tanstack/react-query"

type QueryFn<T> = () => Promise<T>

export const useSearchList = <T>(initialValue = "", queryFn: QueryFn<T>) => {
  const [keyword, setKeyword] = useState(initialValue)

  const onSearch = (value: string) => {
    const trimmedValue = value.trim()
    if (trimmedValue.length === 0) {
      setKeyword("")
      return
    }
    setKeyword(trimmedValue)
  }

  const { data, error, isLoading } = useQuery({
    queryKey: ["search", keyword],
    queryFn,
    enabled: keyword.length > 0,
    throwOnError: true, // 请求失败时自动抛出错误
  })

  // 仅当查询已触发(keyword有效)且加载完成但无数据时抛出错误
  if (keyword.length > 0 && !isLoading && data === undefined) {
    throw new Error("搜索未返回任何数据")
  }

  // 断言data为T,已通过throwOnError和条件判断确保运行时data存在(或已抛出错误)
  return { data: data as T, onSearch, isLoading }
}

方法2:使用useSuspenseQuery

利用React Suspense机制,组件在数据加载时挂起,此时useSuspenseQuery返回的data类型天然为T(无需处理undefined):

import { useState } from "react"
import { useSuspenseQuery } from "@tanstack/react-query"

type QueryFn<T> = () => Promise<T>

export const useSearchList = <T>(initialValue = "", queryFn: QueryFn<T>) => {
  const [keyword, setKeyword] = useState(initialValue)

  const onSearch = (value: string) => {
    const trimmedValue = value.trim()
    if (trimmedValue.length === 0) {
      setKeyword("")
      return
    }
    setKeyword(trimmedValue)
  }

  const { data } = useSuspenseQuery({
    queryKey: ["search", keyword],
    queryFn,
    enabled: keyword.length > 0,
  })

  // 未触发搜索时返回对应默认值(示例为数组类型,可根据T的实际类型调整)
  const safeData = (keyword.length === 0 ? [] : data) as T

  return { data: safeData, onSearch }
}

使用此方法时,需用<Suspense>包裹使用该Hook的组件,处理加载状态。


关于Hook的可用性评估

你当前的Hook存在以下问题,调整后才能正常使用:

  1. 初始状态崩溃:初始时keyword为空,data为undefined,直接抛出错误会导致组件崩溃,必须添加加载状态判断或默认值处理。
  2. 错误处理缺失:未处理请求失败的情况,仅判断data===undefined抛出错误会掩盖真实的请求错误。
  3. 搜索逻辑不完善:onSearch中未处理空输入的清空逻辑,导致keyword可能停留在旧值。

调整后的Hook(如上述两种方案)是可用的,建议根据项目架构选择:

  • 若项目已采用Suspense架构,优先选择方法2,类型更安全且代码简洁。
  • 若需手动处理加载状态,选择方法1,通过throwOnError和类型断言确保类型安全,同时暴露isLoading供组件处理加载UI。

内容的提问来源于stack exchange,提问作者dlwhd5717

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 21:20:24