如何在基于useQuery的自定义React Hook中添加参数合法性校验?
解决React自定义Hook参数校验问题
首先纠正一个常见误区:React Hook的规则是禁止在条件语句、循环、嵌套函数中调用Hook,而非Hook内部不能写条件判断。你的原代码其实没有违反Hook规则,但参数校验的方式可以更合理,下面提供几种优化方案:
方案1:提前参数校验,直接返回错误状态
在Hook最开始就完成参数校验,不符合要求时直接返回预设的错误状态,避免后续不必要的请求逻辑执行:
import { useQuery } from "@tanstack/react-query"; export const useLiquidityPositions = (userAddress: string): GraphQLResponse<LiquidityPositions> => { // 提前校验地址合法性,不符合直接返回错误状态 if (!isAddress(userAddress)) { return { status: 'error', loading: false, error: new Error('无效的用户地址格式'), response: undefined, payload: undefined }; } const { status, isLoading: loading, error, data: response, } = useQuery({ queryKey: ["USER_POSITIONS", userAddress], queryFn: async () => { const res = await getLiquidityPositionsData(userAddress); return res; } }); const payload = response?.data; return { status, loading, error, response, payload } }
方案2:用React Query的enabled控制请求触发
如果希望参数非法时Hook处于闲置状态,参数合法后自动触发请求,可以利用enabled配置项:
import { useQuery } from "@tanstack/react-query"; export const useLiquidityPositions = (userAddress: string): GraphQLResponse<LiquidityPositions> => { const isAddressValid = isAddress(userAddress); const { status, isLoading: loading, error, data: response, } = useQuery({ queryKey: ["USER_POSITIONS", userAddress], queryFn: async () => { const res = await getLiquidityPositionsData(userAddress); return res; }, // 仅当地址合法时才发起请求 enabled: isAddressValid, // 可选:非法状态下的初始数据 initialData: isAddressValid ? undefined : { data: undefined } }); const payload = response?.data; // 单独处理非法参数的状态返回 if (!isAddressValid) { return { status: 'idle', loading: false, error: new Error('无效的用户地址格式'), response: undefined, payload: undefined }; } return { status, loading, error, response, payload } }
方案3:在queryFn内抛出错误替代返回undefined
原代码返回undefined会导致调用方难以区分「参数错误」和「请求无数据」,改成抛出错误更清晰:
import { useQuery } from "@tanstack/react-query"; export const useLiquidityPositions = (userAddress: string): GraphQLResponse<LiquidityPositions> => { const { status, isLoading: loading, error, data: response, } = useQuery({ queryKey: ["USER_POSITIONS", userAddress], queryFn: async () => { if (!isAddress(userAddress)) { throw new Error('无效的用户地址格式'); } const res = await getLiquidityPositionsData(userAddress); return res; } }); const payload = response?.data; return { status, loading, error, response, payload } }
关键说明
- 所有方案都没有违反React Hook规则,因为我们没有在条件语句中调用
useQuery这类Hook,只是在Hook内部做逻辑判断。 - 提前校验能减少无效的资源消耗,
enabled方案更适合参数动态变化的场景,抛出错误则能让调用方通过error字段明确感知问题类型。
内容的提问来源于stack exchange,提问作者code_learner93
相关产品推荐
相关产品推荐

