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
相关产品推荐
相关产品推荐

