React中用户输入文本时如何触发GraphQL的useLazyQuery/useQuery查询
GraphQL+React 自动补全搜索栏条件查询实现
核心原理
React Hooks要求所有Hook必须在组件/自定义Hook的顶层作用域调用,不能嵌套在普通函数、条件判断、循环中。useLazyQuery本身不会在组件挂载时自动发起请求,它会返回一个手动触发查询的函数,你可以在任意事件回调、副作用逻辑、条件判断中调用这个触发函数,完全符合Hooks规则,刚好适配输入长度满足条件再发请求的场景。
现有代码错误点梳理
- Hook调用位置错误:把
useLazyQuery写在了普通函数FetchProducts内部,违反Hooks调用规则 - 事件绑定写法错误:
onChange={e => setInput(e.target.value), triggerFetch }使用了逗号运算符,只会执行最后一个triggerFetch逻辑,setInput无法正常触发状态更新 - 参数不匹配:GraphQL查询定义的入参变量是
$name,但传参时写的是{input},会导致查询拿不到参数报错 - 常量拼写错误:查询常量名
GET_PRODUTCS_QUERY里PRODUCTS漏写了字母C,容易引发引用错误 - 缺少防抖逻辑:输入时每次值变化就立刻发请求,会产生大量无效请求,影响性能
正确实现代码
import { useState, useEffect } from 'react'; import { useLazyQuery, gql } from '@apollo/client'; // 修正拼写后的查询定义,变量名和入参保持一致 const GET_PRODUCTS_QUERY = gql` query getProducts ($name: String!){ products( page: 1, filter: { name: $name }) { results { name, id } } } `; const AutoCompleteSearch = () => { const [input, setInput] = useState(''); // 🔥 必须在组件顶层调用useLazyQuery,和其他Hook保持同级 const [getProducts, { data, loading, error }] = useLazyQuery(GET_PRODUCTS_QUERY); // 统一处理输入变化 const handleInputChange = (e) => { setInput(e.target.value); }; // 监听输入值变化,满足条件时触发查询,加300ms防抖减少无效请求 useEffect(() => { // 输入长度<=3时不触发查询 if (input.length <= 3) return; const timer = setTimeout(() => { // 调用useLazyQuery返回的触发函数,传入匹配的变量 getProducts({ variables: { name: input } }); }, 300); // 组件卸载/输入值变化时清除定时器,避免防抖失效 return () => clearTimeout(timer); }, [input, getProducts]); // 统一渲染搜索结果 const renderSearchResult = () => { if (loading) return <p>Loading...</p>; if (error) return <p>Error :(</p>; if (!data?.products?.results) return null; return data.products.results.map(({ id, name }) => ( <div key={id}> <p>{name}</p> </div> )); }; return ( <div className="search-container"> <input type="text" onChange={handleInputChange} value={input} placeholder="Search..." /> <div className="result-list"> {renderSearchResult()} </div> </div> ); }; export default AutoCompleteSearch;
关键逻辑说明
useLazyQuery的调用位置永远在组件顶层,和useState、useEffect等Hook同级,不会违反Hooks规则- 手动触发查询的核心是调用
useLazyQuery返回的第一个函数(示例中是getProducts),这个函数的调用时机没有限制,可以放在条件判断、事件回调、副作用里 - 自动补全场景必须加防抖,避免用户输入过程中频繁发起请求,300ms是体验比较好的防抖阈值
- 传参时variables的字段名必须和GraphQL查询中定义的变量名完全对应,否则会报变量缺失错误
内容的提问来源于stack exchange,提问作者REF_
相关产品推荐
相关产品推荐

