Skip to content

Commit

Permalink
add input debounce
Browse files Browse the repository at this point in the history
  • Loading branch information
iossocket committed Feb 10, 2025
1 parent 3256121 commit ae524af
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 38 deletions.
75 changes: 39 additions & 36 deletions packages/nextjs/components/Challenges/DynamicSequentialInputs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { useState, useEffect, Dispatch, SetStateAction } from "react";
import {
useState,
useEffect,
Dispatch,
SetStateAction,
useCallback,
} from "react";
import { useDebounceCallback } from "usehooks-ts";

interface InputField {
id: string;
Expand Down Expand Up @@ -103,57 +110,53 @@ export const DynamicSequentialInputs: React.FC<
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [validatedInputs, errors, checking, inputValues]);

const validateAndUpdateInput = async (
id: string,
value: string,
title: string,
): Promise<void> => {
if (value.trim()) {
setChecking((prev) => ({ ...prev, [id]: true }));

try {
await new Promise((resolve) => setTimeout(resolve, 2000));

if (!shouldValidateUrl(title)) {
setErrors((prev) => ({ ...prev, [id]: "" }));
setValidatedInputs((prev) => ({ ...prev, [id]: true }));
} else {
const isValid = validateUrl(value);
if (!isValid) {
setErrors((prev) => ({
...prev,
[id]: "<ERROR> Invalid URL",
}));
setValidatedInputs((prev) => ({ ...prev, [id]: false }));
} else {
const validateAndUpdateInput = useCallback(
async (id: string, value: string, title: string): Promise<void> => {
setErrors((prev) => ({ ...prev, [id]: "" }));
setValidatedInputs((prev) => ({ ...prev, [id]: false }));
if (value.trim()) {
setChecking((prev) => ({ ...prev, [id]: true }));

try {
if (!shouldValidateUrl(title)) {
setErrors((prev) => ({ ...prev, [id]: "" }));
setValidatedInputs((prev) => ({ ...prev, [id]: true }));
} else {
const isValid = validateUrl(value);
if (!isValid) {
setErrors((prev) => ({
...prev,
[id]: "<ERROR> Invalid URL",
}));
setValidatedInputs((prev) => ({ ...prev, [id]: false }));
} else {
setErrors((prev) => ({ ...prev, [id]: "" }));
setValidatedInputs((prev) => ({ ...prev, [id]: true }));
}
}
} finally {
setChecking((prev) => ({ ...prev, [id]: false }));
}
} finally {
setChecking((prev) => ({ ...prev, [id]: false }));
} else {
setValidatedInputs((prev) => ({ ...prev, [id]: false }));
setErrors((prev) => ({ ...prev, [id]: "" }));
}
} else {
setValidatedInputs((prev) => ({ ...prev, [id]: false }));
setErrors((prev) => ({ ...prev, [id]: "" }));
}
};
},
[],
);
const debounced = useDebounceCallback(validateAndUpdateInput, 500);

const handleInputChange = (
id: string,
value: string,
title: string,
): void => {
setInputValues((prev) => ({ ...prev, [id]: value }));
setErrors((prev) => ({ ...prev, [id]: "" }));
setValidatedInputs((prev) => ({ ...prev, [id]: false }));
validateAndUpdateInput(id, value, title);
debounced(id, value, title);
};

const handlePaste = (id: string, value: string, title: string): void => {
setInputValues((prev) => ({ ...prev, [id]: value }));
setErrors((prev) => ({ ...prev, [id]: "" }));
setValidatedInputs((prev) => ({ ...prev, [id]: false }));
validateAndUpdateInput(id, value, title);
};

Expand Down
3 changes: 1 addition & 2 deletions packages/nextjs/components/Challenges/SubmitChallenge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ export const SubmitChallenge = ({ challenge }: { challenge: Challenge }) => {
{},
),
);
const { submissionStatus, submissionTopic, setSubmissionTopic } =
useGlobalState();
const { submissionStatus, setSubmissionTopic } = useGlobalState();
const [loading, setLoading] = useState<boolean>(false);
const modalRef = useRef<HTMLDivElement>(null);
useEffect(() => {
Expand Down

0 comments on commit ae524af

Please sign in to comment.