<InputText/>
에서 엔터 키를 누를 때, <CommonButton/>
을 누를 때, handleSignup을 호출하고 싶음.
그런데, 엔터 키 이벤트가 정상 동작하면 클릭 이벤트가 동작하지 않고, 클릭 이벤트가 정상 동작하며 엔터 키 이벤트가 동작하지 않는다.
다음은 문제가 되었던 코드의 일부분이다.
page.tsx에서 onSubmit을 form 태그에 직접 설정해서, 버튼 클릭 시, 엔터 입력 시 폼이 제출되도록 했다.
버튼 클릭 시 폼이 자동으로 제출되도록 CommonButton의<button>
태그 type을 따로 설정하지 않았다.(button 태그의 기본 type은 submit이므로)
handleSignup함수는 e.preventDefault()로 폼의 기본 동작(새로고침)을 방지하였다.
const handleSignup = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); // 폼의 기본 동작(새로고침) 방지
if (!data.email || !data.password || data.password !== data.password2) {
alert('입력값을 확인해주세요');
return;
}
try {
setLoading(true);
const result = await signup(data);
router.push('/login');
} catch (err) {
console.error('Signup error:', err);
} finally {
setLoading(false);
}
};
return (
<form className="w-full flex flex-col items-center"
onSubmit={handleSignup}>
<InputArea data={data} setData={setData} />
<CommonButton/>
</form>
);
};
interface InputAreaProps {
data: SignupData;
setData: React.Dispatch<React.SetStateAction<SignupData>>;
}
const InputArea = ({ data, setData }: InputAreaProps) => {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setData((prev) => ({ ...prev, [name]: value }));
};
return (
<form>
<InputText
onChange={handleChange}
/>
</form>
);
};
export default InputArea;
const CommonButton = ({
}: ButtonProps) => {
return (
<button
>
{text}
</button>
);
};
export default CommonButton;
이렇게 하면 CommonButton을 클릭해도 아무 일이 일어나지 않는다.
(엔터 키를 누르면 handleSignup 정상 동작)
page.tsx
1. <form>
에서 <CommonButton>
을 빼버렸다.
2. handleSignup
함수의 파라미터 타입을 두 개 넣어주었다.(마우스 이벤트와 폼 이벤트를 모두 받을 수 있도록)
InputArea.tsx
1. <form>
이 중복되고 있어서 빼 주었다.
CommonButton.tsx
1. button 태그의 type을 button으로 설정했다.(form 태그에서 벗어났기 때문)
2. onClick 이벤트를 따로 추가해주었다.
const handleSignup = async (
e?: React.FormEvent<HTMLFormElement> | React.MouseEvent<HTMLButtonElement>,
) => {
if (e && (e as React.FormEvent<HTMLFormElement>).preventDefault) {
(e as React.FormEvent<HTMLFormElement>).preventDefault();
}
if (
!data.email ||
emailRegEx.test(data.email) === false ||
!data.password ||
passwordRegEx.test(data.password) === false ||
data.password !== data.password2
) {
alert('입력값을 확인해주세요');
return;
}
try {
setLoading(true);
const result = await signup(data);
router.push('/login');
} catch (err) {
console.error('Signup error:', err);
} finally {
setLoading(false);
}
};
<form
className="w-full flex flex-col items-center"
onSubmit={handleSignup}
>
<InputArea data={data} setData={setData} />
</form>
<CommonButton
text="회원가입"
onClickEvent={handleSignup}
/>
interface InputAreaProps {
data: SignupData;
setData: React.Dispatch<React.SetStateAction<SignupData>>;
}
const InputArea = ({ data, setData }: InputAreaProps) => {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setData((prev) => ({ ...prev, [name]: value }));
};
return (
<>
<InputText
onChange={handleChange}
/>
</>
);
};
export default InputArea;
interface CommonButtonProps {
onClickEvent?: (e: React.MouseEvent<HTMLButtonElement>) => void;
}
const CommonButton = ({
onClickEvent,
}: CommonButtonProps) => {
return (
<button
type="button"
onClick={onClickEvent}
>
{text}
</button>
);
};
확실하진 않은데 추측해보자면
CommonButton의 버튼 type이 'submit'인데 onClickEvent를 사용했기 때문에 혼란이 야기되었기 때문이다.
CommonButton에 onClickEvent를 따로 내려주지 않았지만 공통 컴포넌트에 onClickEvent 속성이 있어서 문제가 된 듯하다.
맞는 것 같다. 왜냐면 캡쳐화면처럼 하면 두 이벤트 모두 정상동작하기 때문이다.