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

React 实现onChange中searchAddress仅文本变化且间隔5秒执行

实现方案

我们可以通过Ref存储跨渲染的关键状态,结合定时器做动态等待逻辑,完全匹配“输入文本变化+距上次搜索满5秒才触发”的要求,不会出现闭包拿旧值、重复发请求的问题。

核心逻辑拆解

两个触发搜索的必要条件需要同时满足:

  • 当前输入的文本和上一次调用searchAddress时传入的文本不一致
  • 当前时间距离上一次searchAddress实际执行的时间点,已经过去了至少5秒

完整代码调整

首先补充需要引入的useRef Hook(用来存跨渲染的状态,避免闭包陷阱):

import React, { useState, useRef, useEffect } from "react";

在组件内部定义需要的Ref实例,和原有state放在一起:

// 存储上一次执行searchAddress的时间戳
const lastSearchTimeRef = useRef(0);
// 存储上一次searchAddress调用时传入的地址文本
const lastSearchValueRef = useRef("");
// 存储地址搜索的定时器实例,避免连续输入时重复触发
const addressSearchTimerRef = useRef(null);

// 组件卸载时清理定时器,防止内存泄漏
useEffect(() => {
  return () => {
    if (addressSearchTimerRef.current) {
      clearTimeout(addressSearchTimerRef.current);
    }
  };
}, []);

重写onChange里的地址搜索逻辑,原有setErrors、setUserData的逻辑完全保留:

const onChange = async ({ target: { value, name } }) => {
  // 原有通用逻辑不变
  setErrors({ ...errors, [name]: false });
  setUserData({ ...userData, [name]: value });

  // 仅处理地址输入框的搜索逻辑
  if (name === "address") {
    // 每次输入先清除上一个未执行的定时器
    if (addressSearchTimerRef.current) {
      clearTimeout(addressSearchTimerRef.current);
    }

    const COOLDOWN_TIME = 5000; // 固定5秒的搜索冷却间隔
    const now = Date.now();
    const timeSinceLastSearch = now - lastSearchTimeRef.current;
    // 动态计算需要等待的时间:如果已经过了冷却期就等0,否则补够剩余冷却时间
    const waitDuration = Math.max(0, COOLDOWN_TIME - timeSinceLastSearch);

    // 设定定时器,等待到满足时间条件后执行判断
    addressSearchTimerRef.current = setTimeout(async () => {
      // 到点后再次校验两个触发条件
      const isValueChanged = value !== lastSearchValueRef.current;
      const isCooldownPassed = Date.now() - lastSearchTimeRef.current >= COOLDOWN_TIME;
      
      if (isValueChanged && isCooldownPassed) {
        const res = await searchAddress(value);
        if (res.success) {
          setAddressList(res?.results?.matches || []);
          // 搜索执行成功后更新Ref里的状态,作为下一次判断的依据
          lastSearchTimeRef.current = Date.now();
          lastSearchValueRef.current = value;
        }
      }
    }, waitDuration);
  }
};

关键说明

  • 不用普通组件变量存时间戳、文本值的原因:普通变量会在每次组件重渲染时被重置,且存在闭包捕获旧值的问题,useRef可以在组件生命周期内稳定保留最新值,不会出现拿到过期时间、过期文本的问题。
  • 逻辑匹配度:
    • 严格控制两次searchAddress的最小调用间隔为5秒,不会出现高频调用的情况
    • 只有输入文本和上次搜索的内容不一样时,才会真正发起请求,哪怕满足5秒间隔,输入内容没变化也不会重复请求
    • 冷却期内连续输入时,只会拿最后一次输入的文本在冷却结束时触发搜索,不会连续发多个请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 15:36:02