反应选择去抖动异步调用不显示建议

eme*_*pyc 9 javascript reactjs react-select

我正在使用react-select从 api 加载结果并使用lodash.debounce对查询进行抖动:

import React, {useState} from 'react';
import AsyncSelect from 'react-select/lib/Async';
import debounce from 'lodash.debounce';
import {search} from './api';

const _loadSuggestions = (query, callback) => {
  return search(query)
    .then(resp => callback(resp));
};

const loadSuggestions = debounce(_loadSuggestions, 300);

function SearchboxTest() {
  const [inputValue, setInputValue] = useState("");

  const onChange = value => {
    setInputValue(value);
  };

  return (
    <AsyncSelect
      value={inputValue}
      loadOptions={loadSuggestions}
      placeholder="text"
      onChange={onChange}
    />
  )
}

Run Code Online (Sandbox Code Playgroud)

当我第一次在搜索框中输入某些内容时,它似乎工作正常(查询已去抖动并且建议已正确填充),但如果我尝试输入新值,则会按预期触发第二个提取查询,但建议来自不会显示第二个调用(并且我没有收到 react-select 显示的“正在加载...”消息)。

当我不去抖动呼叫时,问题似乎消失了(对于第一次和任何后续呼叫):

import React, {useState} from 'react';
import AsyncSelect from 'react-select/lib/Async';
import {search} from '../../api';

const loadSuggestions = (query, callback) => {
  return search(query)
    .then(resp => callback(resp));
};

function SearchboxTest() {
  const [inputValue, setInputValue] = useState("");

  const onChange = value => {
    setInputValue(value);
  };

  return (
    <AsyncSelect
      value={inputValue}
      loadOptions={loadSuggestions}
      placeholder="text"
      onChange={onChange}
    />
  )
}

Run Code Online (Sandbox Code Playgroud)

知道发生了什么吗?任何帮助理解这个问题将不胜感激。

米;

小智 7

对于所有仍在为此苦苦挣扎并且不想像我一样仅为去抖功能安装 lodash 的人,这是我的解决方案

去抖动功能

export default function debounce(fn, delay = 250) {
    let timeout;

    return (...args) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            fn(...args);
        }, delay);
    };
}
Run Code Online (Sandbox Code Playgroud)

去抖实施

const loadOptionsDebounced = useCallback(
    debounce((inputValue: string, callback: (options: any) => void) => {
        fetchOptions(inputValue).then(options => callback(options))
    }, 500),
    []
);
Run Code Online (Sandbox Code Playgroud)

fetchOptions() 是我的异步获取函数,它返回选项数组


Lok*_* sp 6

使用react-select-async-paginatereact-select包 - 这是一个支持分页的包装器 。检查它的NPM 页面

React-select-async-paginate 与内部谴责有效配合。您可以在 props 中传递 debounce 间隔。

<AsyncPaginate
  value={value}
  loadOptions={loadOptions}
  debounceTimeout={300}
  onChange={setValue}
/>
Run Code Online (Sandbox Code Playgroud)

这是codesandbox示例


Avk*_*ash 5

我也面临同样的问题并得到了这个解决方案。

如果您使用的回调函数,然后你不要需要返回从API的结果。

尝试从_loadSuggestions函数中删除return关键字。如下所示

 import React, {useState} from 'react';
 import AsyncSelect from 'react-select/lib/Async';
 import debounce from 'lodash.debounce';
 import {search} from './api';
 
 const _loadSuggestions = (query, callback) => {
   search(query)
     .then(resp => callback(resp));
 };
 
 const loadSuggestions = debounce(_loadSuggestions, 300);
 
 function SearchboxTest() {
   const [inputValue, setInputValue] = useState("");
 
   const onChange = value => {
     setInputValue(value);
   };
 
   return (
     <AsyncSelect
       value={inputValue}
       loadOptions={loadSuggestions}
       placeholder="text"
       onChange={onChange}
     />
   )
 } 
Run Code Online (Sandbox Code Playgroud)

  • 遇到了同样的问题,这是正确的答案,应该如此标记! (2认同)

Kro*_*rol 1

也许这会对某人有所帮助。

freeze = false //mark delay 
timer //saved timer

loadAddress = async (strSearch: string) => {
   this.freeze = true //set mark for stop calls
   return new Promise(async (res, err) => { //return promise 
   let p = new Promise((res, err) => {
     if(this.freeze) clearTimeout(this.timer) //remove  prev timer 
     this.timer = setTimeout(async () => {
        this.freeze = false
        const r = await this.load(strSearch)//request
        res(r);
     }, 2000)
  })

  p.then(function (x) {
     console.log('log-- ', x);
     res(x);
  })
});
};
Run Code Online (Sandbox Code Playgroud)