lodash debouce 不是 debouncing 函数被多次调用,而不是一次,react hooks react native

问题描述

我正在文本 Input 的 onChange 数组中搜索多个对象,因此我们需要一个去抖动函数来防止对搜索函数进行任何不必要的 API 调用

问题:

debounce 函数等待给定的时间,但它多次调用 API 函数而不仅仅是一次

预期:

去抖动等待时间结束后只调用一次API

代码

const [input,setInput] = useState('');
  const [searchResults,setSearchResults] = useState([]);

  const mockApiCall = async (result,waitingTime = 2000) => {
    await new Promise((resolve) => setTimeout(resolve,waitingTime));

    console.log('making search request',result);
    console.log('post');

    return setSearchResults((prev) => [...prev,result]);
  };

  useEffect(() => {
    console.log('pre');
     const search = _.debounce(mockApiCall,4000);
    search(input);
    // return () => {
    //   _.debounce.cancel();
    // };
  },[input]);

<View style={styles.container}>
      <TextInput
        style={{
          height: 40,borderColor: 'gray',borderWidth: 1,placeholderTextColor: 'gray',}}
        onChangeText={(text) => setInput(text)}
        value={input}
      />
      {searchResults.map((ele) => (
        <Text>{ele}</Text>
      ))}
    </View>

小吃示例:

https://snack.expo.io/@mansouriala/search-using-debounce-rn

解决方法

当你在 debounce 中包装一个函数时,你会得到一个带有内部计时器的新函数(debounced 函数)。您应该记住返回的函数,并使用它来调用 api (snack)。

每当调用去抖动函数时,它的内部计时器都会重置,并再次开始计算超时(在您的情况下为 4000 毫秒)。如果您重新创建该函数,则先前的 debounce 函数不会重置其计时器(不会再次调用),而是会调用包装的函数。

const mockApiCall = useMemo(() => _.debounce(async(result,waitingTime = 2000) => {
  await new Promise((resolve) => setTimeout(resolve,waitingTime));

  console.log('making search request',result);
  console.log('post');

  return setSearchResults((prev) => [...prev,result]);
},4000),[]);

useEffect(() => {
  console.log('pre');

  mockApiCall(input); // call the debounced function
  
  return () => {
    mockApiCall.cancel(); // cancel the debounced function
  };
},[mockApiCall,input]);