import { useRef, useState, memo, useEffect } from 'react'; import PropTypes from 'prop-types'; const noop = () => {}; const DEFAULT_DEBOUNCE_TIMEOUT = 330; // ms const Debounced = ({ children, value, onChange, timeout }) => { const timeoutIdRef = useRef(null); const [innerValue, setInnerValue] = useState(value); useEffect(() => { setInnerValue(value); }, [value]); const handleChange = val => { setInnerValue(val); clearTimeout(timeoutIdRef.current); timeoutIdRef.current = setTimeout(() => { onChange(val); }, timeout); }; const debouncedValue = timeoutIdRef.current ? innerValue : value; return children(debouncedValue, handleChange); }; Debounced.propTypes = { children: PropTypes.func.isRequired, value: PropTypes.any, onChange: PropTypes.func, timeout: PropTypes.number }; Debounced.defaultProps = { children: noop, value: null, onChange: noop, timeout: DEFAULT_DEBOUNCE_TIMEOUT }; export default memo(Debounced);