
React 커스텀 훅은 일반적으로 React 로직을 재사용하고 구성하기 위해 만들어진 함수다.
보통의 상황에서 쓰는 아웃소싱하는 일반 함수와는 달리
React 커스텀 훅은 내부적으로 useState, useEffect, useContext 등 React 훅들을 사용 할 수 있다.

아이디의 검증로직은 "@"를 포함해야 하며,
비밀번호 검증로직은 6자리 이상 써야하는 로그인폼이다.
커스텀 훅을 이용하여 만들어보자.
사용할 파일은 총 세가지다. (App.js , useInput.js , validation.js)
App.js은 최종 컴포넌트 파일
useInput.js은 커스텀훅 파일
validation은 검증로직을 담아놓은 함수파일
최종 컴포넌트 파일
App.js
import { useInput } from "./useInput";
import { isEmail, isNotEmpty, hasMinLength } from "./validation";
function App() {
// 이메일 검증 로직 함수
const validateEmail = (value) => {
return isEmail(value) && isNotEmpty(value);
};
// 비밀번호 검증 로직 함수
const validatePassword = (value) => {
return hasMinLength(value,6);
};
// 객체 구조 분해할당으로 변수 지정하기 (이메일관련부분)
// 우변이 쓰고자하는 변수이다.
// 좌변으로 할당한다.
const {
inputValue: emailValue,
inputValueChange: handleEmailChange,
inputHandlerBlur: handleEmailBlur,
inputEmailHasError: emailHasError,
} = useInput("", validateEmail);
// 객체 구조 분해할당으로 변수 지정하기 (비밀번호관련부분)
// 우변이 쓰고자하는 변수이다.
// 좌변으로 할당한다.
const {
inputValue: passwordValue,
inputValueChange: handlePasswordChange,
inputHandlerBlur: handlePasswordBlur,
inputEmailHasError: passwordHasError,
} = useInput("", validatePassword);
function handleSubmit(event) {
event.preventDefault();
if (emailHasError) {
return;
}
}
return (
<form onSubmit={handleSubmit}>
<div>
<span style = {{margin : '10px'}}>아이디</span>
<input
label="Email"
id="email"
type="email"
name="email"
onBlur={handleEmailBlur}
onChange={handleEmailChange}
value={emailValue}
/>
<span style = {{margin : '10px'}}>비밀번호</span>
<input
label="Password"
id="password"
type="password"
name="password"
onBlur={handlePasswordBlur}
onChange={handlePasswordChange}
value={passwordValue}
/>
{ (emailHasError) && <p>아이디를 제대로 입력해주세요.</p>}
{ (passwordHasError) && <p>비밀번호를 제대로 입력해주세요.</p>}
</div>
<button>Login</button>
</form>
);
}
export default App;
커스텀 훅 파일
useInput.js
import { useState } from "react";
export function useInput(defaultValue,validationFn ) {
// 타이핑된 이메일 or 비밀번호에대한 상태 저장
// 초기값은 useInput 훅을 사용하면서 넘겨온 초기값인 defaultValue로 공백문자가 넘어온다.
const [enterdValue, setEnteredValue ] = useState(defaultValue);
// 이메일 or 비밀번호 입력 상태를 저장한다.
const [edit, setEdit] = useState(false);
// 타이핑된 이메일 or 비밀번호 감지시 실행될 함수
const inputValueChange = (event) => {
setEnteredValue(event.target.value);
// 이걸 써주어야지만 사용자 입장에서 불쾌하지 않은 경험이 될 수 있다.
// 만약 안썻다고 가정해보자
// 한번 edit 상태가 true가 된다면 (onBlur가 true)
// 그 이후에 타이핑하려할때 edit 상태가 쭉 true 상태이다.
// 그러면 발생할 수 있는 문제는 아직 다 입력하지도 않았는데
// 유효성 검사 로직이 발생하여 (eidt상태가 true) 오류메시지가 출력이 될 수 있다.
// 그렇기 떄문에 타이핑하는동안에는 Blur상태가 되기전까지 edit 상태를 false로 해주자.
setEdit(false);
}
// 유효성 검사 로직
// useInput 훅을 사용하면서 넘겨온 validationFn을 이용하여 유효성 검사 로직 결과 변수 저장
const valueIsValid = validationFn(enterdValue);
const inputHandlerBlur = () => {
setEdit(true);
}
return (
{
inputValue : enterdValue,
inputValueChange,
inputHandlerBlur,
inputEmailHasError : edit && !valueIsValid
}
)
}
검증 로직 함수 파일
validation.js
// 이메일에 @를 포함하면 true 반환
// 이메일에 @를 포함하지 않으면 false 반환
export function isEmail(value) {
return value.includes("@");
}
// 공백이아니면 true 반환
// 공백이면 false 반환
export function isNotEmpty(value) {
return value.trim() !== "";
}
export function hasMinLength(value, minLength) {
return value.length >= minLength;
}