๐Ÿงช Challenges

Debounced Search Input

Challenge 4 - Medium

Description

Create a search input component that debounces user input, only triggering the search function after the user stops typing for a set duration.

Objective

Implement debouncing logic and manage timers in React.

1. Example

Explanation

The idea here is that we are going to have an input field that we want to debounce the user input. This means that we want to wait for the user to stop typing for a set duration before we trigger the search function. This is useful when we have a search input that triggers a search function on every key press. This can be a problem when the search function is expensive and we don't want to trigger it on every key press.

Debounced:

2. Implementation

Interface

The interface for this input component is very simple, is just a function that is going to be executed when the user types in the input field and the input field is debounced. We also set the time for that debounce in 1000ms.

0 1 2 3 4 5 interface DebouncedInputPropType extends InputHTMLAttributes<HTMLInputElement>{ onDebouncedChanged: (event: ChangeEvent<HTMLInputElement>) => void; } const DEBOUNCE_TIME = 1000;

State

We are going to have three states in this component. The first one is theevent, which is going to store the event that is triggered when the user types in the input field. The second one is the value, which is going to store the value of the input field. The last one is the debounced value, which is going to store the value of the input field after the debounce time has passed.

0 1 2 3 const [event, setEvent] = useState<ChangeEvent<HTMLInputElement>>(); const [value, setValue] = useState<string>(""); const [debouncedValue, setDebouncedValue] = useState<string>("");

Events

We are going to have two events in this component. The first one is the useEffect, which is going to be triggered every time the value of the input field changes and it's going to reset each time the debounce timer. The second one is the handleInputChange, which is going to be triggered every time the user types in the input field and it's going to save the value and the event that is triggered.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 useEffect(() => { const id = setTimeout(() => { setDebouncedValue(value); if(event) onDebouncedChanged(event); }, DEBOUNCE_TIME); return (() => { clearTimeout(id); }); }, [value]); const handleInputChange = (event: ChangeEvent<HTMLInputElement>): void => { setValue(event.target.value); setEvent(event); };

Render

The render part of this component is very simple. We are going to have an input field that is going to trigger the handleInputChange event every time the user types in the input field. We are also going to show the value of the input field and the debounced value.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 return ( <> <label> Value: <input {...rest} onChange={handleInputChange} value={value} /> </label> <p> Debounced: {debouncedValue} </p> </> );

3. Complete Code

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 'use client' import { ChangeEvent, InputHTMLAttributes, useEffect, useState } from 'react'; interface DebouncedInputPropType extends InputHTMLAttributes<HTMLInputElement>{ onDebouncedChanged: (event: ChangeEvent<HTMLInputElement>) => void; } const DEBOUNCE_TIME = 1000; const DebouncedInput: React.FC<DebouncedInputPropType> = ({onDebouncedChanged, ...rest}) => { const [event, setEvent] = useState<ChangeEvent<HTMLInputElement>>(); const [value, setValue] = useState<string>(""); const [debouncedValue, setDebouncedValue] = useState<string>(""); useEffect(() => { const id = setTimeout(() => { setDebouncedValue(value); if(event) onDebouncedChanged(event); }, DEBOUNCE_TIME); return (() => { clearTimeout(id); }); }, [value]); const handleInputChange = (event: ChangeEvent<HTMLInputElement>): void => { setValue(event.target.value); setEvent(event); }; return ( <> <label> Value: <input {...rest} onChange={handleInputChange} value={value} /> </label> <p> Debounced: {debouncedValue} </p> </> ); }; export default DebouncedInput;
๐Ÿ›๏ธ ๐Ÿงฎ ๐Ÿ“ โš›๏ธ ๐Ÿงช ๐Ÿ