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

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_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:39:18