From 29ee43af248d76c77c350b81ae7feb275e69dca6 Mon Sep 17 00:00:00 2001 From: Dima Rifai <dima.rifai@gmail.com> Date: Tue, 7 Jan 2025 10:42:53 +0200 Subject: [PATCH] Issue #415 - Refactor Events to prevent continous state changes causing slowness --- components/searchRanges/SearchRanges.tsx | 112 +++++++++++------------ 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/components/searchRanges/SearchRanges.tsx b/components/searchRanges/SearchRanges.tsx index fe972df8..61a4360c 100644 --- a/components/searchRanges/SearchRanges.tsx +++ b/components/searchRanges/SearchRanges.tsx @@ -39,33 +39,26 @@ const SearchRanges: React.FC<SearchRangesProps> = ({ // Validate and update numeric values const handleNumericInput = ( - value: string, - fieldSetter: Function, + e: React.ChangeEvent<HTMLInputElement>, allowDecimal: boolean = false ) => { - // If decimals are allowed, preserve the decimal point in the input value - let cleanedValue = allowDecimal - ? value.replace(/[^0-9.]/g, "") // Allow numbers and decimal point - : value.replace(/[^0-9]/g, ""); // Only allow numbers - - // If the decimal is allowed, ensure there is only one decimal point + let cleanedValue = e.target.value; + + // Clean the value based on the logic + cleanedValue = allowDecimal + ? cleanedValue.replace(/[^0-9.]/g, "") // Allow numbers and decimal point + : cleanedValue.replace(/[^0-9]/g, ""); // Only allow numbers + if (allowDecimal && cleanedValue.split(".").length > 2) { - // Remove extra decimals, keeping only the first one cleanedValue = cleanedValue.slice(0, cleanedValue.indexOf(".") + 1) + - cleanedValue.split(".").slice(1).join(""); // Remove all decimals after the first one + cleanedValue.split(".").slice(1).join(""); // Remove extra decimals } - - // Limit the value to a maximum of 15 digits + if (cleanedValue.length > 15) { - cleanedValue = cleanedValue.slice(0, 15); + cleanedValue = cleanedValue.slice(0, 15); // Limit to 15 digits } - // If the cleaned value is empty, set it to undefined - if (cleanedValue === "") { - fieldSetter(undefined); - } else { - fieldSetter(cleanedValue); // Invalid input, set to undefined - } + e.target.value = cleanedValue; }; useEffect(() => { @@ -114,10 +107,13 @@ const SearchRanges: React.FC<SearchRangesProps> = ({ <Input className="w-1/2 border-0 border-b-2 bg-theme" type="text" // Use type="text" to allow custom validation - value={lastBlocksValue || ""} - onChange={(e) => - handleNumericInput(e.target.value,setLastBlocksValue) - } + defaultValue={lastBlocksValue || ""} + onChange={(e) => handleNumericInput(e)} + onBlur={(e) => { + const value = e.target.value; + const numericValue = value ? Number(value) : undefined; + setLastBlocksValue(numericValue); + }} placeholder={"Last"} /> </div> @@ -131,10 +127,13 @@ const SearchRanges: React.FC<SearchRangesProps> = ({ <Input type="text" className="bg-theme border-0 border-b-2 text-text" - value={lastTimeUnitValue || ""} - onChange={(e) => - handleNumericInput(e.target.value,setLastTimeUnitValue,true) - } + defaultValue={lastTimeUnitValue || ""} + onChange={(e) => handleNumericInput(e,true)} + onBlur={(e) => { + const value = e.target.value; + const numericValue = value ? Number(value) : undefined; + setLastTimeUnitValue(numericValue); + }} placeholder={"Last"} /> </div> @@ -173,10 +172,13 @@ const SearchRanges: React.FC<SearchRangesProps> = ({ type="text" className="bg-theme border-0 border-b-2" data-testid="from-block-input" - value={fromBlock || ""} - onChange={(e) => - handleNumericInput(e.target.value,setFromBlock) - } + defaultValue={fromBlock || ""} + onChange={(e) => handleNumericInput(e)} + onBlur={(e) => { + const value = e.target.value; + const numericValue = value ? Number(value) : undefined; + setFromBlock(numericValue); + }} placeholder="From" /> </div> @@ -185,32 +187,30 @@ const SearchRanges: React.FC<SearchRangesProps> = ({ className="bg-theme border-0 border-b-2" data-testid="headblock-number" type="text" - value={toBlock || ""} - onChange={(e) => - handleNumericInput(e.target.value, setToBlock) - } + defaultValue={toBlock || ""} + onChange={(e) => handleNumericInput(e)} // Keep cleaning logic here on change placeholder={"To"} - onBlur={() => { - if ( - Number(toBlock) && - Number(fromBlock) && - !isNaN(Number(toBlock)) && - !isNaN(Number(fromBlock)) && - Number(toBlock) < Number(fromBlock) - ) { - setBlockRangeError( - "To block must be greater than From block" - ); - setToBlock(undefined); // Clear the 'toBlock' field - } else if (Number(toBlock) <= 0 && Number(fromBlock)) { - setBlockRangeError( - "To block must be greater than From block" - ); - setToBlock(undefined); // Clear the 'toBlock' field - } else { - setBlockRangeError(null); // Clear the error message immediately if 'toBlock' is valid + onBlur={(e: React.FocusEvent<HTMLInputElement>) => { + const value = e.target.value; + const numericValue = value ? Number(value) : undefined; // Default to NaN if empty string + if ( + numericValue && + fromBlock && + !isNaN(numericValue) && + !isNaN(Number(fromBlock)) && + numericValue < Number(fromBlock) + ) { + setBlockRangeError("To block must be greater than From block"); + e.target.value = ""; // Clear the 'toBlock' field if validation fails + } else if (numericValue !=undefined && numericValue <= 0 && fromBlock) { + setBlockRangeError("To block must be greater than From block"); + e.target.value = ""; // Clear the 'toBlock' field if validation fails + } else { + setToBlock(numericValue); // Set the state only when validation passes + setBlockRangeError(null); // Clear error if valid + } } - }} + } /> </div> </div> @@ -247,4 +247,4 @@ const SearchRanges: React.FC<SearchRangesProps> = ({ ); }; -export default SearchRanges; +export default SearchRanges; \ No newline at end of file -- GitLab