Closed inkyu0103 closed 1 year ago
The latest updates on your projects. Learn more about Vercel for Git ↗︎
Name | Status | Preview | Comments | Updated (UTC) |
---|---|---|---|---|
badminton-app | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | May 23, 2023 6:57am |
debounce 적용이 안되는 문제 있는데, 어떻게 해결해야할지 감도 안잡힙니다.
isUsableNickname
함수를 디바운스로 처리해야 한다.react-query
사용 여부프로젝트에서 기본적으로 react-query를 사용하고 있기 때문에, isUsableNickname도 custom hook으로 감싸서 사용하고자 했다.
그러면, 다음과 같은 구조를 가지게 된다.
const SignupForms = () => {
const { ... } = useUsableNickname(...)
...
return <SignupFormsView .../>
}
현재 SignupForms에 필요한 비동기 처리 로직은 SignupForms
에서 정의하고 있고, Form과 관련된 내용은 SignupFormsView
에서 처리하고 있다.
useUsableNickname
의 인자로 nickname을 받아와야만 검증이 가능한데 현재 구조로는 불가능한 상황.
const SignupForms = () => {
const methods = useForm();
const { data : isUsableNickname } = useUsableNickname(methods.watch('nickname'));
...
return <FormProvider><SignupFormsView isUsableNickname = {isUsableNickname} .../></FormProvider>
이렇게 하면, useQuery를 사용하여 모든 api를 react-query를 사용하도록 할 수 있다.
사용가능한 닉네임인지 여부를 props로 넘겨주어야 하는 번거로움이 있다.
개인적으로 form과 관련된 내용은 view에서 처리하면 좋겠어서, 굳이 form 관련 로직을 올리지는 않았다. (그리고 애초에 react-query 사용과 무관하게 debounce 문제는 해결되지 않는다.)
기존 debounce 함수는 다음과 같다.
export const debounce = (func: any, time = 200) => {
let timer: ReturnType<typeof setTimeout>;
return (...args: unknown[]) => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => func(...args), time);
};
};
문제는 어떤 값을 반환하는 함수를 debounce로 감싸게 되면, 그 값을 사용할 수가 없게 된다.
const handleValidateNickname = debouce((nickname) => isUsableNickname(nickname) , 200)
<input
className="w-full py-2 text-sm rounded-md shadow-md outline-none indent-2 "
placeholder="사용하실 별명을 입력해주세요"
{...register("nickname", {
required: {
value: true,
message: "별명을 입력해주세요",
},
validate: {
isUsableNickname: async (nickname) =>(await handleValidateNickname(nickname)) || "이미 사용중인 별명입니다.",
},
})}
/>
해당 코드로 validate를 실행하게 되면, 항상 이미 사용중인 별명입니다
를 볼 수 있다.
debounce 함수 자체에서 아무런 값도 반환하지 않기 때문에, 암시적으로 undefined
를 반환하게 되고, falsy한 값이므로 ||
연산자에 의해 두 번째 값으로 넘어가게 된다.
다음과 같은 방식으로 debounce를 수정하였다. 다만, 기존에 사용하던 debounce와 호환이 되는지 여부를 확인해야해서 extractDebounce.ts
라는 파일에 작성했다.
export const extractDebounce = (func: any, time = 200) => {
let timer: ReturnType<typeof setTimeout>;
return (...args: unknown[]) => {
if (timer) {
clearTimeout(timer);
}
return new Promise((resolve, reject) => {
timer = setTimeout(async () => {
try {
const result = await func(...args);
resolve(result);
} catch (error) {
reject(error);
}
}, time);
});
};
};
기존 debounce와 다른 점은, Promise를 리턴한다는 점이다. 그렇게 되면 외부에서 await 키워드와 함께 사용하면, 원하는 값을 받을 수 있게된다.
const handleValidateNickname = extractDebounce((nickname) => isUsableNickname(nickname) , 200)
<input
className="w-full py-2 text-sm rounded-md shadow-md outline-none indent-2 "
placeholder="사용하실 별명을 입력해주세요"
{...register("nickname", {
required: {
value: true,
message: "별명을 입력해주세요",
},
validate: {
isUsableNickname: async (nickname) =>(await handleValidateNickname(nickname)) || "이미 사용중인 별명입니다.",
},
})}
/>
설명
유니크한 사용자 별명을 입력받도록 변경합니다.
관련 이슈
Fix #116
변경사항
BE
이와 별도로 테이블 네이밍이 모두 대문자로 되어있어, 소문자로 변경하였습니다.
FE
isUsableNickname
스크린샷