Skip to content

Instantly share code, notes, and snippets.

@Danziger
Created February 13, 2020 22:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Danziger/8952f19602e396ddd5aff931809422a0 to your computer and use it in GitHub Desktop.
Save Danziger/8952f19602e396ddd5aff931809422a0 to your computer and use it in GitHub Desktop.
Form Hooks
import { useCallback, useEffect, useRef, useState } from 'react';
import { FIELD_THROTTLE_RATE } from '../../components/form/form.constants';
import { getFakeChangeEvent } from '../../components/form/utils/form-events.utils';
import { FormValue } from '../../data/common/types/common.types';
import { useThrottledCallback } from './throttled-callback.hook';
export function useInputState<V extends FormValue = FormValue>(
initialValue: V,
onChange: (e: React.ChangeEvent<HTMLInputElement>, value: V) => void,
) {
// Could be initialized with a ref from the parent:
const inputRef = useRef<HTMLInputElement>(null);
const [value, setValue] = useState<V>(initialValue);
// If initialValue changes, propagate the change to state:
useEffect(() => setValue(initialValue), [initialValue]);
// TODO: Maybe we could create a useDebouncedCallback instead?
const throttledOnChange = useThrottledCallback(onChange, FIELD_THROTTLE_RATE, [onChange]);
// We could change updateValue to make it controlled or uncontrolled:
const updateValue = useCallback((
nextValueOrF: V | ((prevValue: V) => V),
e: React.ChangeEvent<HTMLInputElement> = null,
immediate: boolean = false,
) => {
const event = immediate && e || getFakeChangeEvent(inputRef.current);
const cb = immediate ? onChange : throttledOnChange;
if (typeof nextValueOrF === 'function') {
setValue((prevValue) => {
const nextValue = nextValueOrF(prevValue);
cb(event, nextValue);
return nextValue;
});
} else {
setValue(nextValueOrF);
cb(event, nextValueOrF);
}
}, []);
return { inputRef, value, updateValue };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment