diff --git a/components/form.js b/components/form.js index bdbbcf19..3f523d11 100644 --- a/components/form.js +++ b/components/form.js @@ -24,6 +24,7 @@ import { numWithUnits } from '../lib/format' import textAreaCaret from 'textarea-caret' import ReactDatePicker from 'react-datepicker' import 'react-datepicker/dist/react-datepicker.css' +import { debounce } from './use-debounce-callback' export function SubmitButton ({ children, variant, value, onClick, disabled, cost, ...props @@ -290,7 +291,7 @@ function FormGroup ({ className, label, children }) { function InputInner ({ prepend, append, hint, showValid, onChange, onBlur, overrideValue, - innerRef, noForm, clear, onKeyDown, inputGroupClassName, debounce, maxLength, + innerRef, noForm, clear, onKeyDown, inputGroupClassName, debounce: debounceTime, maxLength, ...props }) { const [field, meta, helpers] = noForm ? [{}, {}, {}] : useField(props) @@ -317,17 +318,11 @@ function InputInner ({ const invalid = (!formik || formik.submitCount > 0) && meta.touched && meta.error - const debounceRef = useRef(-1) - - useEffect(() => { - if (debounceRef.current !== -1) { - clearTimeout(debounceRef.current) + useEffect(debounce(() => { + if (!noForm && !isNaN(debounceTime) && debounceTime > 0) { + formik.validateForm() } - if (!noForm && !isNaN(debounce) && debounce > 0) { - debounceRef.current = setTimeout(() => formik.validateForm(), debounce) - } - return () => clearTimeout(debounceRef.current) - }, [noForm, formik, field.value]) + }, debounceTime), [noForm, formik, field.value]) const remaining = maxLength && maxLength - (field.value || '').length diff --git a/components/use-debounce-callback.js b/components/use-debounce-callback.js new file mode 100644 index 00000000..3d945f63 --- /dev/null +++ b/components/use-debounce-callback.js @@ -0,0 +1,23 @@ +import { useCallback, useEffect, useState } from 'react' + +export function debounce (fn, time) { + let timeoutId + return wrapper + function wrapper (...args) { + if (timeoutId) { + clearTimeout(timeoutId) + } + timeoutId = setTimeout(() => { + timeoutId = null + fn(...args) + }, time) + // return a function that clears the timeout for use in useEffect cleanup + return () => clearTimeout(timeoutId) + } +} + +export default function useDebounceCallback (fn, time, deps = []) { + const [args, setArgs] = useState([]) + useEffect(debounce(() => fn(...args), time), [fn, time, args, ...deps]) + return useCallback((...args) => setArgs(args), []) +} diff --git a/package-lock.json b/package-lock.json index c4562a35..16f12a70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,6 @@ "graphql-type-json": "^0.3.2", "jose1": "npm:jose@^1.27.2", "ln-service": "^56.11.0", - "lodash.debounce": "^4.0.8", "mathjs": "^11.9.1", "mdast-util-find-and-replace": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", diff --git a/package.json b/package.json index 3fcb7907..af34d1df 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "graphql-type-json": "^0.3.2", "jose1": "npm:jose@^1.27.2", "ln-service": "^56.11.0", - "lodash.debounce": "^4.0.8", "mathjs": "^11.9.1", "mdast-util-find-and-replace": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", diff --git a/pages/wallet.js b/pages/wallet.js index d011c212..788ed1bf 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -8,7 +8,7 @@ import { CenterLayout } from '../components/layout' import InputGroup from 'react-bootstrap/InputGroup' import { WithdrawlSkeleton } from './withdrawals/[id]' import { useMe } from '../components/me' -import { useCallback, useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import { requestProvider } from 'webln' import Alert from 'react-bootstrap/Alert' import { CREATE_WITHDRAWL, SEND_TO_LNADDR } from '../fragments/wallet' @@ -21,7 +21,7 @@ import styles from '../components/user-header.module.css' import HiddenWalletSummary from '../components/hidden-wallet-summary' import AccordianItem from '../components/accordian-item' import { lnAddrOptions } from '../lib/lnurl' -import debounce from 'lodash.debounce' +import useDebounceCallback from '../components/use-debounce-callback' export const getServerSideProps = getGetServerSideProps({ authRequired: true }) @@ -301,7 +301,7 @@ export function LnAddrWithdrawal () { const [addrOptions, setAddrOptions] = useState(defaultOptions) const [formSchema, setFormSchema] = useState(lnAddrSchema()) - const onAddrChange = useCallback(debounce(async (formik, e) => { + const onAddrChange = useDebounceCallback(async (formik, e) => { let options try { options = await lnAddrOptions(e.target.value) @@ -313,7 +313,7 @@ export function LnAddrWithdrawal () { setAddrOptions(options) setFormSchema(lnAddrSchema(options)) - }, 500), [lnAddrOptions, lnAddrSchema]) + }, 500, [lnAddrOptions, lnAddrSchema]) return ( <>