antd renderFormItem AutoComplete结合防抖导致防抖失效的解决办法

简介: antd renderFormItem AutoComplete结合防抖导致防抖失效的解决办法

业务背景

我们有一个需求是在用户输入用例名称的时候,系统根据名称去匹配公共用例库中的用例模块展示在下拉框中,然后用户可选择想要的模块导入其中的用例:

但是如果用户每输入一个字符就去调用接口查询的话,这样就太频繁了,会给服务端造成不小的压力,所以就需要使用防抖方法来进行限流控制。这里的方案如下:

因为antd提供了AutoComplete方法能够很方便的在表格中实现编辑行的操作,这里也就不重新造轮子了,然后结合lodash提供的debounce方法进行防抖设置,也就是每隔200毫秒去搜索一次,完整的代码如下:

const batchSearchDebounce = debounce(async (keyWords) => {
    if (keyWords) {
      return await searchComStdMod({ search: keyWords }).then((res) => {
        const data: any[] = [];
        res.data.forEach((item: any) => {
          data.push({
            label: (
              <>
                <Tag color="blue">公共模块</Tag>
                {item.label}
              </>
            ),
            value: item.value,
            name: item.label,
          });
        });
        setSearchData(data);
      });
    }
  }, 200);
   <AutoComplete
        style={{ width: width }}
        placeholder="请输入用例名称"
        onSelect={(_: any, mod: any) => {
          comStandardCasesAll({ module_id: mod.value }, REQ_LIST).then((res) => {
            setFormData({ cases: res.data, module_name: mod.name });
            setVisible(true);
          });
        }}
        {...(type === 'single' ? {} : { value: batchData.value })}
        onChange={async (keyWords) => {
          batchData.onChange(keyWords);
          await batchSearchDebounce(keyWords); //防抖会失效
        }}
        options={searchData}
      />

但在使用的过程中发现防抖并没有生效,我每输入一个文字就会搜索一次,1秒内输入10下就会有10个请求发出去:

造成这个问题的原因是什么呢

是因为AutoComplete中的onChange的事件,当每次改变的时候都会创建一个debounce方法,所以onChange事件触发10次,就会有10个防抖函数并执行。

如何解决

我们可以使用useCallback将防抖方法进行缓存,避免不必要的刷新重建就可以了。

如下所示,useCallback有两个参数:

useCallback(fn, deps)`

fn:要缓存的函数,在初始渲染期间,React将返回你的函数。在下一次渲染时,如果依赖关系(也就是deps)自上次渲染以来没有改变,React将再次给你相同的函数。

deps: 是一个数组,当里面的元素发生改变的时候会重新渲染函数。

因为,我们结合useCallback这里我们将batchSearchDebounce 做一下修改即可:

const batchSearchDebounce = useCallback(
    debounce(async (keyWords: string) => {
      if (keyWords) {
        batchData.onChange(keyWords);
        return await searchComStdMod({ search: keyWords }).then((res) => {
          const data: any[] = [];
          res.data.forEach((item: any) => {
            data.push({
              label: (
                <>
                  <Tag color="blue">公共模块</Tag>
                  {item.label}
                </>
              ),
              value: item.value,
              name: item.label,
            });
          });
          setSearchData(data);
        });
      }
    }, 200),
    [],
  );

使用useCallback之后就不会出现上述的问题了,防抖方法也就生效了:

useCallback 它可以让你在重新渲染之间缓存函数,避免函数冗余的重新渲染,以此来提高性能,没想到因为这样的机制也能解决掉一些逻辑问题。

目录
相关文章
|
7月前
|
JavaScript 前端开发 UED
jQuery 自动刷新页面但不闪烁的实现方法
jQuery 自动刷新页面但不闪烁的实现方法
|
JavaScript 前端开发
vue 中使用防抖和节流,防止重复点击或重复上拉加载
vue 中使用防抖和节流,防止重复点击或重复上拉加载
|
前端开发
Vue3输入框focus失效
Vue3引入elementplus的输入框el-input,如果想在鼠标点击即搜索框获得焦点后发生变化,那就得用到css的:focus选择器
551 1
|
4月前
|
JavaScript UED
如何在Vue3项目中使用防抖节流技巧
在Vue 3项目中使用防抖和节流技巧以优化组件性能,包括使用`lodash`库和自定义实现这两种方法。
542 0
如何在Vue3项目中使用防抖节流技巧
|
4月前
|
JavaScript 前端开发
解决在JS中阻止定时器“重复”开启问题、Vue中定时器的使用
这篇文章讨论了在JavaScript和Vue中如何避免定时器重复开启的问题,并提供了一个模拟场景和代码示例,演示了在开启新定时器前清除旧定时器的方法。
解决在JS中阻止定时器“重复”开启问题、Vue中定时器的使用
|
7月前
|
JavaScript
Vue 编写(preventReClick)防暴点 +防抖(debounce)和节流(throttle)函数
Vue 编写(preventReClick)防暴点 +防抖(debounce)和节流(throttle)函数
439 0
|
JavaScript
vue3中input事件防抖处理
vue3中input事件防抖处理
257 2
|
7月前
|
前端开发 UED
React 防抖与节流用法
React 防抖与节流用法
189 0
|
7月前
|
JavaScript 前端开发
js的节流和防抖
js的节流和防抖
42 0
|
7月前
|
JavaScript 前端开发 UED