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

React Gatsby搜索框更新时如何触发API重渲染更新组件

Gatsby React 搜索功能不生效修复

问题根因

当前代码存在核心问题导致搜索无法触发更新:

  • 数据请求的useEffect依赖数组为空[],仅会在组件首次挂载时执行1次,后续输入框更新search状态时,不会触发接口重新请求
  • 请求头myHeaders定义在组件顶层作用域,每次组件重渲染都会重新创建,且多次调用getPeople时会重复往headers里追加相同字段,累积后容易触发请求异常
  • 无防抖、无请求取消逻辑时,输入过程会高频发送请求,还容易出现请求竞态,导致最终展示结果和输入内容不匹配

修复步骤

  1. 将search加入useEffect的依赖项,移除不必要的eslint禁用注释
  2. 把Headers实例初始化逻辑移到getPeople函数内部,每次请求生成新的headers实例,避免字段重复追加
  3. 增加输入防抖、请求取消逻辑,优化使用体验、避免结果错乱
  4. 给输入框绑定value属性改为标准受控组件,避免输入值和状态不同步
  5. 拼接搜索参数时用encodeURIComponent处理特殊字符,避免请求参数格式错误

修复后完整代码

import React, { useState, useEffect, Fragment } from 'react'

const PeoplePage = () => {
  const [search, setSearch] = useState("")
  const [people, setPeople] = useState()

  const getPeople = async (controller) => {
    // 每次请求新建headers实例,避免重复追加字段
    const myHeaders = new Headers();
    myHeaders.append("Access-Control-Request-Headers", process.env.GATSBY_PEOPLE_ACCESS_CONTROL);
    myHeaders.append("Authorization", process.env.GATSBY_PEOPLE_BEARER);
    const requestOptions = {
      method: 'GET',
      headers: myHeaders,
      redirect: 'follow',
      signal: controller.signal // 绑定取消信号,处理竞态问题
    };
    try {   
      const response = await fetch(
        `${process.env.GATSBY_PEOPLE_API}&search=${encodeURIComponent(search)}`, 
        requestOptions
      );
      const result = await response.json();
      setPeople(result)
    } catch (err) { 
      // 忽略主动取消请求抛出的正常错误
      if (err.name !== 'AbortError') console.error(err); 
    }
  };

  const searchUpdate = (e) => {
    setSearch(e.target.value)
  }

  useEffect(() => {
    // 500ms防抖,避免输入过程中高频发送请求
    const timer = setTimeout(() => {
      const controller = new AbortController()
      getPeople(controller)
      // 搜索词变化、组件卸载时取消未完成的请求
      return () => controller.abort()
    }, 500)

    return () => clearTimeout(timer)
  }, [search]) // 把search加入依赖,搜索词变化时自动触发请求

  return (
    <Fragment>
      <input placeholder="Search.." onChange={searchUpdate} value={search} />
      <div className="people">
        {people ? Object.values(people).map(person => {
          return (
            <div id={"person-"+person.id} key={person.id} >
              {person.name}
            </div>
          )
        }) : "Not available.."}
      </div>
    </Fragment >
  )
}

export default PeoplePage

内容的提问来源于stack exchange,提问作者iamaprogrammer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:51:22