import { useState } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "../ui/button";
import { Textarea } from "@/components/ui/textarea";
export default function WriteProfile() {
const [nickname, setNickname] = useState("");
const [nicknameError, setNicknameError] = useState("");
const [introError, setIntroError] = useState("");
const [introduce, setIntroduce] = useState("");
const nicknameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNickname(e.target.value);
};
const introChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setIntroduce(e.target.value);
};
const handleError = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
let hasError = false;
if (nickname === "") {
setNicknameError("닉네임을 입력해주셔야 합니다.");
hasError = true;
} else {
setNicknameError("");
}
if (introduce === "") {
setIntroError("자기소개를 입력해주셔야 합니다.");
hasError = true;
} else {
setIntroError("");
}
if (!hasError) {
console.log("폼 제출 완료");
}
};
return (
<>
<form onSubmit={handleError}>
<section>
<label
htmlFor="nickname"
className=" font-pretendardSemiBold text-xl out-of-range:border-red-500"
>
닉네임 컬러 및 선택
</label>
<Input
id="nickname"
type="text"
placeholder="닉네임을 입력해주세요"
minLength={1}
required
value={nickname}
onChange={nicknameChange}
className="mt-[26px]"
/>
<span>{nicknameError}</span>
</section>
<section className="flex flex-col">
<label htmlFor="introduce">자기소개 입력칸</label>
<Textarea
placeholder="자기소개를 입력해주세요"
value={introduce}
minLength={5}
required
onChange={introChange}
/>
<span>{introError}</span>
</section>
</form>
<Button type="submit">프로필 업데이트 하기</Button>
</>
);
}
이렇게 코드를 작성했다.
인풋에 아무런 값이 적혀져 있지 않는 상태로 폼을 제출하게 될 경우 에러메시지가 나오도록 하고 싶은데 왜인지.. 적용이 안된다... 대체 왜지..?(분명 전에는 잘 만들었는데 말이다...ㅜ)

이렇게 알림창이 뜬다!
그런데 나는 오류메시지를 만들고 싶다.
그래서 총 코드가
import { useState } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "../ui/button";
import { Textarea } from "@/components/ui/textarea";
export default function WriteProfile() {
const [nickname, setNickname] = useState("");
const [nicknameError, setNicknameError] = useState("");
const [introError, setIntroError] = useState("");
const [introduce, setIntroduce] = useState("");
const nicknameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNickname(e.target.value);
};
const introChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setIntroduce(e.target.value);
};
const handleError = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
let hasError = false;
if (nickname.length === 0) {
setNicknameError("닉네임을 입력해주셔야 합니다.");
hasError = true;
}
if (introduce.length === 0) {
setIntroError("자기소개를 입력해주셔야 합니다.");
hasError = true;
}
};
return (
<>
<form onSubmit={handleError}>
<section>
<label
htmlFor="nickname"
className=" font-pretendardSemiBold text-xl out-of-range:border-red-500"
>
닉네임 컬러 및 선택
</label>
<Input
id="nickname"
type="text"
placeholder="닉네임을 입력해주세요"
minLength={1}
value={nickname}
onChange={nicknameChange}
className="mt-[26px]"
/>
{nicknameError && <span>{nicknameError}</span>}
</section>
<section className="flex flex-col">
<label htmlFor="introduce">자기소개 입력칸</label>
<Textarea
placeholder="자기소개를 입력해주세요"
value={introduce}
minLength={5}
onChange={introChange}
/>
{introError && <span>{introError}</span>}
</section>
<Button type="submit">프로필 업데이트 하기</Button>
</form>
</>
);
}
그랬더니

이런식으로 빈칸으로 제출 버튼을 눌렀을 때 오류 메시지가 잘 떴다..!
정말이지 바보같은 실수...
코딩을 하다보면 엄청난 실수보다는 알고 있었음에도 놓쳐서 헤메는 경우가 꽤 많다고 생각한다.
꼼꼼하게 하려고 노력하고 고민하는 시간이 필수적이다..!
그런 고민의 과정마저 즐겨야 진정한 승자..ㅎ
기본 HTML5 폼 검증이 활성화 된 경우, 브라우저가 자체적으로 입력 검증을 수행하고 사용자에게 에러 메시지를 표시한다.
이 기본 동작은 브라우저에 내장된 검증 로직에 따라 이루어진다.
사용자가 폼을 제출하려고 할 때 발생하게 된다.
그러하여, 기본 HTML5 폼 검증이 작동시 커스텀 검증 메시지가 표시되지 않는 이유!
HTML5 required, type, minLength 등의 속성을 사용하면, 브라우저는 기본 폼 검증을 수행하게 된다.
이 기본 검증이 작동할 경우, 브라우저는 폼 제출을 중단하고 자체 에러 메시지를 표시한다.
기본 폼 검증이 실패하면 브라우저는 폼 제출을 차단한다.
폼이 제출되지 않기 때문에 onSubmit이벤트 핸들러에 도달하지 않는다.
따라서 커스텀 검증 로직이 실행될 기회가 없게 된다!!!
브라우저는 기본 폼 검증 실패 시 사용자에게 내장된 에러 메시지를 표시한다.
이 메시지는 브라우저가 기본적으로 제공하는 스타일과 내용을 가지고 있으며, 사용자가 작성한 커스텀 에러 메시지보다 우선적이다.
즉 기본 폼 검증을 비활성화하고 커스텀 메시지를 표시하려면, noValidate 속성을 사용하여 브라우저의 기본 폼 검증을 비활성화해야 한다.
그러면 폼 제출이 커스텀 검증 로직으로 넘어가서 JavaScript를 통해 검증된 후에 사용자에게 에러 메시지를 표시할 수 있다.
그렇게 수정된
"use client";
import { Input } from "@/components/ui/input";
import { Button } from "../ui/button";
import { useState } from "react";
import { Textarea } from "@/components/ui/textarea";
export default function WriteProfile() {
const [nickname, setNickname] = useState("");
const [nicknameError, setNicknameError] = useState("");
const [introError, setIntroError] = useState("");
const [introduce, setIntroduce] = useState("");
const nicknameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNickname(e.target.value);
if (e.target.value.length > 0) {
setNicknameError("");
}
};
const introChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setIntroduce(e.target.value);
if (e.target.value.length > 0) {
setIntroError("");
} else if (e.target.value.length >= 2) {
setIntroError("");
}
};
const handleError = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (nickname === "") {
setNicknameError("닉네임을 작성해주셔야 합니다.");
}
if (introduce === "") {
setIntroError("자기소개를 작성해주셔야 합니다.");
} else if (introduce.length < 2) {
setIntroError("자기소개는 2글자 이상 작성해야 합니다.");
}
};
return (
<>
<form onSubmit={handleError}>
<section>
<label
htmlFor="nickname"
className=" font-pretendardSemiBold text-xl out-of-range:border-red-500"
>
닉네임 컬러 및 선택
</label>
<Input
id="nickname"
type="text"
placeholder="닉네임을 입력해주세요"
minLength={1}
value={nickname}
onChange={nicknameChange}
className="mt-[26px]"
/>
{nicknameError && <span>{nicknameError}</span>}
</section>
<section className="flex flex-col">
<label htmlFor="introduce">자기소개 입력칸</label>
<Textarea
placeholder="자기소개를 입력해주세요"
value={introduce}
onChange={introChange}
/>
{introError && <span>{introError}</span>}
</section>
<Button type="submit">프로필 업데이트 하기</Button>
</form>
</>
);
}