Skip to content

Instantly share code, notes, and snippets.

@librz
Created October 24, 2025 06:47
Show Gist options
  • Select an option

  • Save librz/dcde72b68733dda55cfd6291a77287cf to your computer and use it in GitHub Desktop.

Select an option

Save librz/dcde72b68733dda55cfd6291a77287cf to your computer and use it in GitHub Desktop.
Input with auto debounce
import { debounce } from "es-toolkit";
import {
useCallback,
useRef,
useState,
type ChangeEventHandler,
type InputHTMLAttributes,
} from "react";
import { useUpdateEffect } from "react-use";
export type InputProps = InputHTMLAttributes<HTMLInputElement> & {
/**
* if set to true, debounce onChange
* note: input text itself is never debounced, user typing shouldn't have any lag
*/
debounced?: boolean;
debounceMs?: number;
};
export function Input(props: InputProps) {
const {
value: valueProp,
onChange: onChangeProp,
debounced = false,
debounceMs = 300,
...inputProps
} = props;
const [internalValue, setInternalValue] = useState(valueProp);
useUpdateEffect(() => {
setInternalValue(valueProp);
}, [valueProp]);
const onChangeDebounced = useCallback(
debounce<ChangeEventHandler<HTMLInputElement>>((e) => {
onChangeProp && onChangeProp(e);
}, debounceMs),
[debounceMs],
);
return (
<input
value={internalValue}
onChange={(e) => {
setInternalValue(e.target.value);
if (!onChangeProp) {
return;
}
// intercept onChange, debounce if needed
const onChangeHandler = debounced ? onChangeDebounced : onChangeProp;
onChangeHandler(e);
}}
{...inputProps}
/>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment