Skip to content

Commit

Permalink
DebouncedInput updates from PR (send event if pending and unmounting …
Browse files Browse the repository at this point in the history
…the component, move default interval value for better visibility)
  • Loading branch information
thsparks committed Feb 1, 2024
1 parent cc03024 commit 3f6314c
Showing 1 changed file with 27 additions and 12 deletions.
39 changes: 27 additions & 12 deletions teachertool/src/components/DebouncedInput.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,42 @@
import { useRef } from "react";
import { useEffect, useRef } from "react";
import { Input, InputProps } from "react-common/components/controls/Input";

export interface DebouncedInputProps extends InputProps {
intervalMs?: number | undefined;
intervalMs?: number; // Default 500 ms
}

// This functions like the React Common Input, but debounces onChange calls
// so they only fire once every `interval` milliseconds (defined in props)
export const DebouncedInput: React.FC<DebouncedInputProps> = props => {
// This functions like the React Common Input, but debounces onChange calls,
// so if onChange is called multiple times in quick succession, it will only
// be executed once after a pause of the specified `interval` in milliseconds.
export const DebouncedInput: React.FC<DebouncedInputProps> = ({ intervalMs = 500, ...props }) => {
const timerId = useRef<NodeJS.Timeout | undefined>(undefined);
const latestValue = useRef<string>("");

const sendChange = () => {
if (props.onChange) {
props.onChange(latestValue.current);
}
};

// If the timer is pending and the component unmounts,
// clear the timer and fire the onChange event immediately.
useEffect(() => {
return () => {
if (timerId.current) {
clearTimeout(timerId.current);
sendChange();
}
};
}, []);

const onChangeDebounce = (newValue: string) => {
latestValue.current = newValue;

if (timerId.current) {
clearTimeout(timerId.current);
}

timerId.current = setTimeout(() => {
if (!props.onChange) {
return;
}

props.onChange(newValue);
}, props.intervalMs ?? 500);
timerId.current = setTimeout(sendChange, intervalMs);
};

return <Input {...props} onChange={onChangeDebounce} />;
Expand Down

0 comments on commit 3f6314c

Please sign in to comment.