React中useQuery使用错误?触发无效Hook调用报错
问题分析与解决方法
首先,你的错误确实是因为违反了React Hooks的使用规则。React明确要求:所有Hooks(包括useQuery这种基于Hooks封装的函数)必须直接在函数组件的顶层作用域调用,不能嵌套在普通函数、条件判断、循环或者回调函数内部。
你代码里的核心问题出在handleSubmit函数中调用useQuery:
const handleSubmit = (params) => { useQuery(params.userQueryString); // 此处违反Hooks规则 };
正确实现方案
要实现提交时重新发起查询,有两种常用的可行方式:
方案1:利用useQuery的refetch方法
保留顶层的useQuery,通过修改查询变量或手动调用refetch触发重新查询:
const Vis = ({ queryString }) => { const [userQueryString, setUserQueryString] = useState(queryString); // 使用state中的userQueryString作为查询变量 const { loading, error, data, refetch } = useQuery(FOO_QUERY, { variables: { queryString: userQueryString }, onCompleted: (data) => { console.log(data); }, }); const handleSubmit = (params) => { // 更新本地状态,自动触发查询重新执行 setUserQueryString(params.userQueryString); // 或者手动调用refetch传入新参数: // refetch({ queryString: params.userQueryString }); }; return ( <div> <RenderGraph data={formatData(data)}> <QueryForm userQueryString={userQueryString} queryFunction={handleSubmit}> </QueryForm> </RenderGraph> </div> ); };
方案2:使用useLazyQuery延迟查询
如果需要仅在用户触发操作(如提交)时才发起查询,而非组件挂载时自动执行,可使用useLazyQuery:
import { useLazyQuery } from '@apollo/client'; const Vis = ({ queryString }) => { const [userQueryString, setUserQueryString] = useState(queryString); // useLazyQuery返回触发查询的函数和查询结果对象 const [fetchData, { loading, error, data }] = useLazyQuery(FOO_QUERY, { onCompleted: (data) => { console.log(data); }, }); const handleSubmit = (params) => { // 提交时手动调用fetchData发起查询 fetchData({ variables: { queryString: params.userQueryString } }); // 更新本地状态(按需) setUserQueryString(params.userQueryString); }; return ( <div> <RenderGraph data={formatData(data)}> <QueryForm userQueryString={userQueryString} queryFunction={handleSubmit}> </QueryForm> </RenderGraph> </div> ); };
额外注意事项
- 不要直接修改props的值:你代码中
queryString = 'some query'会覆盖传入的props,这是不规范的,应使用state管理可变的查询字符串。 - 确保React与Apollo Client版本兼容,避免因版本不匹配导致的Hook调用异常。
内容的提问来源于stack exchange,提问作者easythrees
相关产品推荐
相关产品推荐

