Last active
October 27, 2021 06:05
-
-
Save lotharschulz/bd9126c1baf48f5ec10ed20b77d1bd00 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// please see also the accompanying blog post | |
// https://www.lotharschulz.info/2021/10/14/how-to-create-a-react-frontend-to-debounce-text-input-persistence-in-firebase-firestore/ | |
function Elements() { | |
const defaultDelayInMillis = 5000; // default delay 5 seconds | |
const [dbValue, setDBValue] = useState(""); | |
const [delayFieldDisabled, setdelayFieldDisabled] = useState(true) | |
const [debounceDelay, setDebounceDelay] = useState(defaultDelayInMillis) | |
const collectionLabel = "data"; | |
const documentLabel = "doc"; | |
useEffect(() => { | |
return onSnapshot(doc(db, collectionLabel, documentLabel), (snapshot) => { | |
const data = snapshot.data(); | |
data === undefined ? setDBValue("") : setDBValue(data.text); | |
}); | |
}, [dbValue, setDBValue]); | |
const saveToDB = (fieldValue: string) => { | |
const maxLength = 100; | |
if (fieldValue.length < maxLength){ | |
const docRef = doc(db, collectionLabel, documentLabel); | |
const data = JSON.stringify(fieldValue).substring(1, fieldValue.length+1); | |
setDoc(docRef, { | |
text: data, | |
updatedAt: Date.now() | |
}); | |
} | |
} | |
const saveFieldValue = (fieldId: number, fieldValue: string) => saveToDB(fieldValue); | |
const saveFieldValueDebounced = AwesomeDebouncePromise( | |
saveFieldValue, | |
debounceDelay, | |
{ key: fieldId => fieldId }, | |
); | |
const onFieldTextChangeDebounce = async (fieldId: number, fieldValue: string) => await saveFieldValueDebounced(fieldId, fieldValue); | |
const onFieldTextChangeDirect = (fieldValue: string) => saveToDB(fieldValue); | |
const onDelayInputFieldChange = (fieldValue: string) => { | |
const onlyNums = fieldValue.replace(/[^0-9]/g, ''); | |
parseInt(onlyNums) > 0 ? setDebounceDelay(parseInt(onlyNums)) : setDebounceDelay(0); | |
}; | |
const handleChangedCheckbox = (event: React.ChangeEvent<HTMLInputElement>) => | |
setdelayFieldDisabled(!event.target.checked); | |
const onTextFieldChange = (fieldId: number, fieldValue: string) => | |
delayFieldDisabled ? onFieldTextChangeDirect(fieldValue) : onFieldTextChangeDebounce(fieldId, fieldValue); | |
return ( | |
<> | |
<p> | |
<TextField | |
style={{ width: "100%" }} | |
id="input-basic" | |
onChange={e => onTextFieldChange(1, e.target.value)} | |
label="text input field" | |
variant="outlined" | |
/> | |
</p> | |
<br/> | |
<p> | |
<TextField | |
style={{ width: "100%" }} | |
id="display-basic" | |
value={dbValue} | |
label="read only database value" | |
variant="outlined" | |
inputProps={ | |
{ readOnly: true, } | |
} | |
/> | |
</p> | |
<hr/> | |
<p> | |
<FormControlLabel | |
control={ | |
<Checkbox onChange={handleChangedCheckbox} /> | |
} | |
label="debounce" | |
/> | |
<TextField | |
style={{ width: "50%" }} | |
id="debounce-delay" | |
value={debounceDelay} | |
onChange={e => onDelayInputFieldChange(e.target.value)} | |
label="debounce in milliseconds" | |
variant="outlined" | |
disabled={delayFieldDisabled} | |
/> | |
</p> | |
</> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment