Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react debounce with useEffect

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>
  )

}
like image 275
eugene Avatar asked Mar 01 '26 06:03

eugene


1 Answers

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.

like image 137
jurcola Avatar answered Mar 03 '26 20:03

jurcola



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!