3

I'm trying to implement autocomplete search with debounce,

Below is my attempt using lodash's debounce, it seems debouncing is not working.

I'm seeing every character being searched as I type

   const [query, setQuery] = useState('')
   const _search = () => {
     console.log('query: ', query)
     // network search request
   }

   const search = _.debounce(_search, 300)

   useEffect(() => {
     search()
   }, [query])

   const handleChangeQuery = useCallback((query) => {
     setQuery(query)
   })

** edit **

Following works, yes I mostly got hint from https://stackoverflow.com/a/54666498/433570 although I think it is very slightly different

Where the linked post chains event setQuery => useEffect => useRef => debounce Here I'm chaining useCallback => useRef => debounce

Although the core problem (according to the linked post) is you recreate variables inside your component everytime your functional component is called.

useRef saves it.

I understood useCallback remembers the function but it also loses when the dependant variable changes

It's kinda vague what it means, I thought useCallback gives you memoized function, but if you change the following code from useRef to useCallback it stops working.. (event though we don't use dependant variable such as useCallback(() => {}, [var])

const ReviewMetaSelect = (props) => {

  const [query, setQuery] = useState('')


  const search = useRef(_.debounce(query => {

    console.log('query: ', query)

  }, 300))


  // or u can use this
  //const search = useCallback(_.debounce(query => {

    //console.log('query: ', query)

  //}, 300), [])    

   const handleChangeQuery = useCallback((query) => {
     setQuery(query)
     search.current(query) // or search(query) with useCallback
   })

  return (
    <View>
      <TextInput
        value={query}
        onChangeText={handleChangeQuery}
      />
    </View>
  )

}
eugene
  • 39,839
  • 68
  • 255
  • 489
  • Does this answer your question? [How to use throttle or debounce with React Hook?](https://stackoverflow.com/questions/54666401/how-to-use-throttle-or-debounce-with-react-hook) – skyboyer Mar 21 '20 at 12:53
  • Yes the answer helps a lot.. I added what I found.. – eugene Mar 21 '20 at 13:13
  • 1
    @eugene It's solved here https://stackoverflow.com/questions/60789246/react-why-using-debounce-and-setstate-in-the-same-callback-not-work#60789246 – keikai Mar 21 '20 at 15:12
  • @keikei I just confirmed it works .. thank you – eugene Mar 27 '20 at 10:09

1 Answers1

5

You can create your custom component Input with a debounce (or use inside another component), with out necesity of a library

For example like some this:

import React, { useEffect, useState } from 'react';

const InputDebounce = () => {

    const [text, setText] = useState('');

    useEffect(() => {
        const timeoutId = setTimeout(() => {
            console.log(text)
            //some function here
        }, 500);

        return () => clearTimeout(timeoutId)
    }, [text])


    return <input type="text" onChange={(e) => setText(e.target.value)} />
};

export default InputDebounce;

Is very important define the clearTimeOut a return insde of the useEffect,to this working ok.

jurcola
  • 359
  • 4
  • 7
  • This will call the setTimeout function once on every page load.. which might in most cases is not the feature generally you see – atul mishra May 17 '22 at 17:18