Optimizing User Experience with useDebounce() Hook
Tags: react, javascript, webdev, programming
Published: 2023-07-01 05:23:12

Optimizing User experience is one of the key elements in Web Development. One aspect of improving the user experience is debouncing

## What is debouncing?

Debouncing in simple terms is just delaying a function to make sure that it doesn’t get called too often which can lead to performance issues. You might wanna ask, **why’d we want to delay the function?**

Nice Question!

The answer is what if the function uses heavy resources in our software? We cannot afford it to get called too often. For example, if the function is calling an API we wouldn’t wanna call it too many times.

## Real world Example

Suppose we are creating a live search features where whenever user types the name of a product, the list updates in real-time. Now, let’s suppose for every key stroke that user makes an API is getting called. 

Suppose the user is searching for `MacBook Air` . In this case 11 subsequent API requests (for each character) will be made to the server, which can increase server load and cause performance issues. 

![Server Load](https://media2.giphy.com/media/WhFfFPCEDXpBe/giphy.gif?cid=ecf05e47ogo5xqjnf5nks11fqh6epqqumf7cw9lff7vf53az&ep=v1_gifs_search&rid=giphy.gif&ct=g)

## Solution

The Solution is debouncing the function. Which means that we will add a delay to the function to make sure the user has finished typing. And if the user types again we will just cancel the previous call and call the function again when the user finishes.

In this tutorial we’re gonna create a useDebounce() hook for this purpose.

```tsx
import { useEffect, useState } from 'react'

export function useDebounce<T>(value: T, delay?: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value)

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay || 500)

    return () => {
      clearTimeout(timer)
    }
  }, [value, delay])

  return debouncedValue
}
```

Now, let's dive deeper into the live search example we've discussed earlier. As mentioned before, the hook will update the value of `debouncedValue` state every `delay` milliseconds. This means that every time the user types a character, the hook waits for `delay` milliseconds before updating the `debouncedValue`. If during that duration the value passed is changed, the previous timeout is cleared and a new timeout is set. This ensures that the hook only returns the final value after the user has stopped typing for at least `delay` milliseconds. Once the timeout is over, the `debouncedValue` is changed to the final value. This way, we can avoid unnecessary API calls or other expensive operations that would slow down the user interface.

## Usage of the hook

```tsx
export default function Component() {
  const [value, setValue] = useState<string>('')
  const debouncedValue = useDebounce<string>(value, 500)

  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value)
  }

  // Fetch API (optional)
  useEffect(() => {
    // Do fetch here...
    // Triggers when "debouncedValue" changes
  }, [debouncedValue])

  return (
    <div>
      <p>Value real-time: {value}</p>
      <p>Debounced value: {debouncedValue}</p>

      <input type="text" value={value} onChange={handleChange} />
    </div>
  )
}
```

## Resources

https://usehooks-ts.com/react-hook/use-debounce

## Conclusion

I hope you enjoyed this tutorial. If you think I made a mistake somewhere let me know in the comment section.

### My Socials

Twitter - https://twitter.com/shaancodes

Instagram - https://www.instagram.com/shaancodes/

GitHub - https://github.com/shaan-alam/