skip to Main Content

I am importing just the debounce function from lodash:

import debounce from "lodash/debounce"

the function I wish to debounce is an async function called ‘fetchUsers’. So I am creating the debounced version of the function thusly:

const debouncedFetchUsers = debounce(fetchUsers, 5000)

This gets called from a useEffect when the inputValue changes:

useEffect(() => {
        if (inputValue.length > 2) {
            debouncedFetchUsers(inputValue);
        } else {
            setUsers([]);
        }
    }, [inputValue, debouncedFetchUsers]);

If I type 5 characters into the inputValue text field in quick succession, the fetchUsers function is getting called (with correct inputValue) 3 times ….after a delay of 5 seconds from each character press.

Of note, if I include debouncedFetchUsers in my useEffect dependency array, I get an infinite re-render loop. This makes me think the function is getting re-created every render.

That brings me to the answer of Lodash debounce in react so then I wrap my debouncedFetchUsers in a useCallback, thusly:

const debouncedFetchUsers = useCallback(
    debounce(fetchUsers, 5000),
    [fetchUsers]
);

This doesn’t fix the infinite useEffect loop.

So, I followed up the chain and wrapped fetchUsers in a useCallback. This solved the issue.

For completeness, this is the fetchUsers function:

const fetchUsers = useCallback(async (needle) => {
    console.log(`FetchingUsers...${needle}`);
    setIsLoading(true);
    const response = await fetch(`http://localhost:7000/users?needle=${needle}`);
    const data = await response.json();
    setUsers(data);
    setIsLoading(false);
    console.log(`DONE FetchingUsers...${needle}`);
}, []);

.

2

Answers


  1. Always make sure the dependency arrays are populated correctly. You ESlint configured with right rules for react hooks like exhaustive dependency rule to get all the dependencies right.

    You might need to pass fetchUsers function as a dependency in the useCallback, like below:

    const debouncedFetchUsers = useCallback(
        debounce(fetchUsers, 5000),
        [fetchUsers]
    );
    

    If you want to avoid this you can directly write the function logic in the use callback:

    const debouncedFetchUsers = useCallback(
        debounce(() => {
          // your function logic here
        }, 5000),
        []
    );
    

    Also the useEffect should have the memoized callback as a dependency:

    useEffect(() => {
            if (inputValue.length > 2) {
                debouncedFetchUsers();
            } else {
                setUsers([]);
            }
        }, [inputValue, debouncedFetchUsers]);
    

    See if this works

    Login or Signup to reply.
  2.     Remove  inputValue from dependency Array  this causing re rendering
        component 
    
        Remove this functionality from useEffect and do it onChange function
    
    
    
    
       const onChangeText =() =>{
          if (inputValue.length > 2) {
                    debouncedFetchUsers();
                } else {
                    setUsers([]);
                }
           }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search