From b5131d12a31aa647184805449e12293a77dbdbaa Mon Sep 17 00:00:00 2001 From: Maciej Ziarkowski Date: Tue, 7 Jan 2020 18:26:23 +0000 Subject: [PATCH] Add throttling of autofill API calls --- .../autofill/autofillDropdown.tsx | 6 ++++- app/src/frontend/hooks/useThrottledValue.ts | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 app/src/frontend/hooks/useThrottledValue.ts diff --git a/app/src/frontend/building/data-components/autofill/autofillDropdown.tsx b/app/src/frontend/building/data-components/autofill/autofillDropdown.tsx index ac0d500c..6fadcd33 100644 --- a/app/src/frontend/building/data-components/autofill/autofillDropdown.tsx +++ b/app/src/frontend/building/data-components/autofill/autofillDropdown.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react'; import './autofillDropdown.css'; import { apiGet } from '../../../apiHelpers'; +import { useThrottledValue } from '../../../hooks/useThrottledValue'; interface AutofillDropdownProps { fieldName: string; @@ -21,6 +22,9 @@ interface AutofillOption { export const AutofillDropdown: React.FC = props => { const [options, setOptions] = useState(null); + // use both throttled and debounced field value as trigger for update + const throttledFieldValue = useThrottledValue(props.fieldValue, 1000); + useEffect(() => { const doAsync = async () => { if (!props.editing || props.fieldValue === '') return setOptions(null); @@ -34,7 +38,7 @@ export const AutofillDropdown: React.FC = props => { }; doAsync(); - }, [props.editing, props.fieldName, props.fieldValue]); + }, [props.editing, props.fieldName, throttledFieldValue]); if (!props.editing || options == undefined) return null; diff --git a/app/src/frontend/hooks/useThrottledValue.ts b/app/src/frontend/hooks/useThrottledValue.ts new file mode 100644 index 00000000..2d19e247 --- /dev/null +++ b/app/src/frontend/hooks/useThrottledValue.ts @@ -0,0 +1,22 @@ +import { useEffect, useRef, useState } from 'react'; + +export function useThrottledValue(value: V, delay: number): V { + const [throttledValue, setThrottledValue] = useState(value); + let lastUpdated = useRef(Date.now()); + + useEffect(() => { + const timer = setTimeout(() => { + if(Date.now() - lastUpdated.current >= delay) { + setThrottledValue(value); + console.log('Updating to', value); + lastUpdated.current = Date.now(); + } + }, delay - (Date.now() - lastUpdated.current)); + + return () => { + clearTimeout(timer); + }; + }, [delay, value]); + + return throttledValue; +}