From d5f7855adf0f76928afde9ff32f66177c29209e5 Mon Sep 17 00:00:00 2001 From: SatsAllDay <128755788+SatsAllDay@users.noreply.github.com> Date: Wed, 9 Aug 2023 18:06:22 -0400 Subject: [PATCH] Debounce API requests on edit nym by 500ms (#387) Support an optional debounce prop on Input component If provided, the debounce is applied to the validation of the containing form, imperatively invoking form validation after debounce is finalized Also required introducing the `validateOnChange` prop on `Form` which gets passed to `Formik`, and defaults to true, just as it does in `Formik`. Imperatively invoking form validation seemed to be the only way to debounce the validation call through formik. --- components/form.js | 17 +++++++++++++++-- components/user-header.js | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/components/form.js b/components/form.js index ee481a4f..4688f1e2 100644 --- a/components/form.js +++ b/components/form.js @@ -219,7 +219,7 @@ function FormGroup ({ className, label, children }) { function InputInner ({ prepend, append, hint, showValid, onChange, overrideValue, - innerRef, noForm, clear, onKeyDown, ...props + innerRef, noForm, clear, onKeyDown, debounce, ...props }) { const [field, meta, helpers] = noForm ? [{}, {}, {}] : useField(props) const formik = noForm ? null : useFormikContext() @@ -245,6 +245,18 @@ function InputInner ({ const invalid = (!formik || formik.submitCount > 0) && meta.touched && meta.error + const debounceRef = useRef(-1) + + useEffect(() => { + if (debounceRef.current !== -1) { + clearTimeout(debounceRef.current) + } + if (!noForm && !isNaN(debounce) && debounce > 0) { + debounceRef.current = setTimeout(() => formik.validateForm(), debounce) + } + return () => clearTimeout(debounceRef.current) + }, [noForm, formik, field.value]) + return ( <> @@ -446,13 +458,14 @@ export function Checkbox ({ children, label, groupClassName, hiddenLabel, extra, const StorageKeyPrefixContext = createContext() export function Form ({ - initial, schema, onSubmit, children, initialError, validateImmediately, storageKeyPrefix, ...props + initial, schema, onSubmit, children, initialError, validateImmediately, storageKeyPrefix, validateOnChange = true, ...props }) { const [error, setError] = useState(initialError) return ( { if (name === user.name) { setEditting(false) @@ -137,6 +138,7 @@ function NymEdit ({ user, setEditting }) { autoFocus groupClassName={styles.usernameForm} showValid + debounce={500} /> setEditting(true)}>save