1. validation 방법
1) 양식 제출 후 체크인 경우
(1) ref 사용
장점 : 코딩이 간결
단점 : 값 재설정이 어려움
import { useRef } from "react";
export default function Login() {
const email = useRef();
const password = useRef();
function handleSubmit(event) {
event.preventDefault();
const enteredEmail = email.current.value;
const enteredPassword = password.current.value;
}
return (
<form onSubmit={handleSubmit}>
<h2>Login</h2>
<div className="control-row">
<div className="control no-margin">
<label htmlFor="email">Email</label>
<input id="email" type="email" name="email" ref={email} />
</div>
<div className="control no-margin">
<label htmlFor="password">Password</label>
<input id="password" type="password" name="password" ref={password} />
</div>
</div>
<p className="form-actions">
<button className="button button-flat">Reset</button>
<button className="button">Login</button>
</p>
</form>
);
}
event.preventDefault(); : Http 양식을 전송하는 브라우저의 기본 구성을 막아, 새로고침을 막아줌
(2) new FormData();
장점 : 값이 많을 때 한번에 추출 가능
import { useState } from "react";
export default function Signup() {
const [passwordsAreNotEqual, setPasswordAreNotEqual] = useState(false);
function handleSubmit(event) {
event.preventDefault();
// name prop required
const fd = new FormData(event.target);
const acquisitionChannel = fd.getAll("acquisition");
const data = Object.fromEntries(fd.entries());
data.acquisition = acquisitionChannel;
if (data.password !== data["confirm-password"]) {
setPasswordAreNotEqual(true);
return;
}
// event.target.reset();
}
return (
<form onSubmit={handleSubmit}>
<h2>Welcome on board!</h2>
<p>We just need a little bit of data from you to get you started 🚀</p>
<div className="control">
<label htmlFor="email">Email</label>
<input id="email" type="email" name="email" required />
</div>
<div className="control-row">
<div className="control">
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
name="password"
required
minLength={6}
/>
</div>
<div className="control">
<label htmlFor="confirm-password">Confirm Password</label>
<input
id="confirm-password"
type="password"
name="confirm-password"
/>
<div className="control-error">
{passwordsAreNotEqual && <p>Passwords are not equal</p>}
</div>
</div>
</div>
<hr />
<div className="control-row">
<div className="control">
<label htmlFor="first-name">First Name</label>
<input type="text" id="first-name" name="first-name" required />
</div>
<div className="control">
<label htmlFor="last-name">Last Name</label>
<input type="text" id="last-name" name="last-name" required />
</div>
</div>
<div className="control">
<label htmlFor="phone">What best describes your role?</label>
<select id="role" name="role" required>
<option value="student">Student</option>
<option value="teacher">Teacher</option>
<option value="employee">Employee</option>
<option value="founder">Founder</option>
<option value="other">Other</option>
</select>
</div>
<fieldset>
<legend>How did you find us?</legend>
<div className="control">
<input
type="checkbox"
id="google"
name="acquisition"
value="google"
/>
<label htmlFor="google">Google</label>
</div>
<div className="control">
<input
type="checkbox"
id="friend"
name="acquisition"
value="friend"
/>
<label htmlFor="friend">Referred by friend</label>
</div>
<div className="control">
<input type="checkbox" id="other" name="acquisition" value="other" />
<label htmlFor="other">Other</label>
</div>
</fieldset>
<div className="control">
<label htmlFor="terms-and-conditions">
<input
type="checkbox"
id="terms-and-conditions"
name="terms"
required
/>
I agree to the terms and conditions
</label>
</div>
<p className="form-actions">
<button type="reset" className="button button-flat">
Reset
</button>
<button type="submit" className="button">
Sign up
</button>
</p>
</form>
);
}
- name prop 필수
- const data = Object.fromEntries(fd.entries()); 모든 값을 객체화 해서 얻을 수 있음
- const acquisitionChannel = fd.getAll("acquisition"); : 다양한 값이 있는 입력창 ex) checkbox는 Object.fromEntries(fd.entries());에 빠져있어서 따로 값을 추출함
(3) required와 type 활용 (내장 기능)
<div className="control">
<label htmlFor="email">Email</label>
<input id="email" type="email" name="email" required />
</div>
- Form 안에 type 지정하면 그 type에 맞는 양식인지 자동으로 확인 해줌
- required 입력하면 필수값으로 지정되어 값이 비어있으면 warning 문구를 자동으로 띄워줌
- minLength={숫자} 입력하면 최소로 작성해야하는 글자수 를 지정 할 수 있음
2) 값이 바뀔때마다 validation 하는 경우
주의 * 사용자 기반 Validation check를 하더라도, 제출 기반의 Valication check를 넣어야 함
(1) useState 사용
단점 : 오류 메시지가 이르게 보여질 수 있음
(2) Custom Hook 생성
컴포넌트
import { useState } from "react";
import Input from "./Input";
import { isEmail, isNotEmpty, hasMinLength } from "../util/validation.js";
import { useInput } from "../hooks/useInput";
export default function Login() {
const {
value: emailValue,
handleInputChange: handleEmailChange,
handleInputBlur: handleEmailBlur,
hasError: emailHasError,
} = useInput("", (value) => isEmail(value) && isNotEmpty(value));
const {
value: passwordValue,
handleInputChange: handlePasswordChange,
handleInputBlur: handlePasswordBlur,
hasError: passwordHasError,
} = useInput("", (value) => {
hasMinLength(value, 6);
});
function handleSubmit(event) {
event.preventDefault();
if (emailHasError || passwordHasError) {
return;
}
}
return (
<form onSubmit={handleSubmit}>
<h2>Login</h2>
<div className="control-row">
<Input
label="Email"
id="email"
type="email"
name="email"
onBlur={handleEmailBlur}
onChange={handleEmailChange}
value={emailValue}
error={emailHasError && "Please enter a valid email"}
/>
<Input
label="Password"
id="password"
type="password"
name="password"
onBlur={handlePasswordBlur}
onChange={handlePasswordChange}
value={passwordValue}
error={passwordHasError && "Please enter a valid password"}
/>
</div>
<p className="form-actions">
<button type="reset" className="button button-flat">
Reset
</button>
<button className="button">Login</button>
</p>
</form>
);
}
useInput.js 커스텀 훅
import { useState } from "react";
export function useInput(defaultValue, validationFn) {
const [enteredValue, setEnteredValue] = useState(defaultValue);
const [didEdit, setDidEdit] = useState(false);
const valueIsValid = validationFn(enteredValue);
function handleInputChange(event) {
setEnteredValue(event.target.value);
setDidEdit(false);
}
function handleInputBlur() {
setDidEdit(true);
}
return {
value: enteredValue,
handleInputChange,
handleInputBlur,
hasError: didEdit && !valueIsValid,
};
}
(3) Library사용
- React Hook Form
- Formik
2. form reset 방법
1) form 내에 type=reset 버튼을 추가
<button type="reset" className="button button-flat">
Reset
</button>
2) submit handler에 event.target.reset();
function handleSubmit(event) {
event.preventDefault();
// name prop required
const fd = new FormData(event.target);
const acquisitionChannel = fd.getAll("acquisition");
const data = Object.fromEntries(fd.entries());
data.acquisition = acquisitionChannel;
if (data.password !== data["confirm-password"]) {
setPasswordAreNotEqual(true);
return;
}
// event.target.reset();
}
'React' 카테고리의 다른 글
[React] router (0) | 2024.04.23 |
---|---|
[React] Redux (0) | 2024.04.19 |
[React] Custom Hook (0) | 2024.04.17 |
[React] Http 연결, fetch (0) | 2024.04.16 |
[React] memo, useMemo (0) | 2024.04.11 |