JAVASCRIPT
Declarative setTimeout with useTimeout
Learn to create a `useTimeout` React hook for declarative, self-cleaning `setTimeout` operations, making it easy to schedule actions without memory leaks.
import { useEffect, useRef } from 'react';
const useTimeout = (callback, delay) => {
const savedCallback = useRef(callback);
// Remember the latest callback if it changes.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the timeout.
useEffect(() => {
if (delay !== null) {
const handler = () => savedCallback.current();
const id = setTimeout(handler, delay);
return () => clearTimeout(id);
}
}, [delay]); // Only re-run if the delay changes
};
export default useTimeout;
// Example Usage:
// function NotificationMessage() {
// const [message, setMessage] = useState('Message will disappear in 3 seconds!');
//
// useTimeout(() => {
// setMessage('Message disappeared!');
// }, 3000);
//
// return <p>{message}</p>;
// }
//
// function DebouncedInput() {
// const [inputValue, setInputValue] = useState('');
// const [debouncedValue, setDebouncedValue] = useState('');
//
// useTimeout(() => {
// setDebouncedValue(inputValue);
// }, 500); // 500ms debounce
//
// return (
// <div>
// <input
// type="text"
// value={inputValue}
// onChange={(e) => setInputValue(e.target.value)}
// placeholder="Type something..."
// />
// <p>Live: {inputValue}</p>
// <p>Debounced: {debouncedValue}</p>
// </div>
// );
// }
How it works: The `useTimeout` hook provides a declarative and resilient way to use `setTimeout` within React components. It ensures that the timer is properly cleared when the component unmounts or if the `delay` changes, preventing memory leaks and stale closures. By storing the `callback` in a ref, it guarantees that the latest callback function is always executed when the timeout triggers, even if the component re-renders multiple times before the timer completes.