React表单提交调用useQuery触发钩子错误,如何正确实现?
解决方案
错误原因
useQuery 是 React Hook,必须严格遵循 Hook 规则:只能在函数组件的顶层作用域或自定义 Hook 中调用,不能放在事件处理函数、循环、条件判断这类嵌套逻辑里。你把 useQuery 写在表单提交的 formSubmit 函数内,直接违反了这个规则,因此触发了错误。
正确实现:使用 useLazyQuery
Apollo Client 提供的 useLazyQuery 专门解决这类按需触发请求的场景——它不会自动执行请求,而是返回一个可手动调用的触发函数,完全符合表单提交的需求。
修改后的完整代码示例:
import { useLazyQuery } from '@apollo/client'; import { useState, SetStateAction } from 'react'; // 请确保已导入对应的GraphQL类型和查询语句 // import { GetShoeDetailsQuery, GetShoeDetailsQueryVariables } from './generated/graphql'; // import getShoeDetailsQuery from './queries/getShoeDetails'; function ShoeSearchForm() { const [shoe, setShoe] = useState(''); // 初始化useLazyQuery,获取触发函数和请求状态 const [triggerShoeQuery, { data, loading, error }] = useLazyQuery<GetShoeDetailsQuery, GetShoeDetailsQueryVariables>( getShoeDetailsQuery ); const formSubmit = (e: React.FormEvent) => { e.preventDefault(); // 表单提交时手动触发请求,传入参数 triggerShoeQuery({ variables: { name: String(shoe), }, }); }; return ( <form onSubmit={formSubmit}> <input type="text" value={shoe} onChange={(e: { target: { value: SetStateAction<string> } }) => { setShoe(e.target.value); }} placeholder="输入鞋款名称" /> <button type="submit">查询详情</button> {/* 可选:添加状态反馈 */} {loading && <p>加载中...</p>} {error && <p>请求失败:{error.message}</p>} {data && <pre>{JSON.stringify(data, null, 2)}</pre>} </form> ); }
关键细节说明
useLazyQuery返回一个数组:第一个元素是触发请求的函数(示例中命名为triggerShoeQuery),第二个元素包含请求状态(data/loading/error),结构和useQuery完全一致。- 修正了原代码的语法错误:比如
input的onChange是属性,需用onChange={...}而非onChange: ...;表单提交函数需接收事件参数e并声明类型。 - 给
input绑定了value属性,形成受控组件,避免 React 控制台警告。
内容的提问来源于stack exchange,提问作者ttmt
相关产品推荐
相关产品推荐

