home
메인페이지는 최대한 심플하게 작업했다.
배경 이미지 위에 로고와 캐치프레이즈, Sign in/ Sign up 버튼이 있다.
버튼에는 hover
시에 반투명한 배경 색상이 생기면서 폰트 색이 변경되도록 하였는데,
이때 transition
을 부여해 부드러운 애니메이션 효과가 있도록 하였다.
const [signIn, setSignIn] = useState(true);
메인 페이지는 전체 한번만 렌더링 되고, 오른쪽 박스 내부의 부분만 'signIn state' 를 활용하여 true일 경우 sign in, false일 경우 sign up 으로 교체되도록 하였다.
interface Props{ }
interface 를 작성할 때 useState 의 'setState' 의 경우 작성에 주의가 필요했다 !
기본 형태의 type을 소괄호 안에 value: type
형식으로 작성하고 => void;
를 작성해준다.
setBooleanState: (value: boolean) => void;
setObjectState: (value: { [key: string]: string }) => void;
sign up
inputValue 관리
input 값을 onChange
를 통해 'inputValue state'에 저장한다.
const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {
const name: string = e.target.name;
const value: string = e.target.value;
setInputValue({ ...inputValue, [name]: value });
checkForm();
};
이때 자바스크립트와는 달리 이벤트에도 타입을 지정해야했다. e: React.ChangeEvent<HTMLInputElement>
로 지정하도록 해서 any
를 방지했다.
이벤트 핸들링을 위한 타입은 같은 onChange
라고 해도 요소에 따라서도 타입이 바뀌기 때문에 필요할 때마다 해당 타입을 찾아 사용하도록 한다 !
유효성 검사
const checkForm = () => {
if (!inputValue.email || !inputValue.email.includes("@")) {
setErrorMessage((prev) => ({
...prev,
email: "이메일 양식을 지켜주세요(@를 포함해주세요)",
}));
setErrorCheck(false);
} else if (inputValue && inputValue.email.includes("@")) {
setErrorMessage((prev) => ({ ...prev, email: "" }));
}
유효성 검사는 필요한 조건에 충족하지 않을 경우 'errorMessage state'에 에러 문구를 추가하고, 충족할 경우 'errorMessage state'의 해당 key-value를 ''로 초기화 하도록 했다.
if (Object.values(errorMessage).every((value) => value === "")) {
setErrorCheck(true);
}
모든 값이 '' 빈문자열 일 경우 상위 컴포넌트에서 prop 받은 'errorCheck'의 상태를 true로 변경하고 이 errorCheck의 상태를 조건으로 'true'일 경우에만 signIn 통신이 진행되도록 구현하였다.
<S.Input
name={title}
placeholder={placeholder}
type={type}
onChange={handleInput}
onBlur={checkForm}
></S.Input>
<S.Warning>{errorMessage[title]}</S.Warning>
렌더링 되는 부분의 코드인데 렌더링될 때 title을 활용하여 값을 사용하려 했더니, 타입에 'any' 지정으로 또 이슈가 생겼다... 동적으로 처리할 값이고, 이미 모든 key에 타입을 부여해뒀는데 어떻게 처리해야 하나 시간이 조금 걸렸다.
const [errorMessage, setErrorMessage] = useState<{
email: string;
password: string;
nickname: string;
[key: string]: string;
}>({ email: " ", password: " ", nickname: " " });
[key: string]: string;
를 통해 기본 타입을 부여해 줌으로써 해결할 수 있었다.
onChange/onBlur
유효성 검사를 위한 부분을 처음에는 onChange
로만 작성하였는데 테스트 시 메일 작성 중 자동완성 기능을 사용하니 검사 조건 '@'가 포함되어 있어도 인식하지 못하는 문제를 발견했다.
그래서 해당 함수를 input의 onChange
에 걸려있는 input값 관리 함수 'handleInput' 안에 실행시켜줌으로써 작성과 동시에 실행될 수 있도록 하면서, 자동완성 기능 사용을 고려하여 onBlur
에도 작성해 포커스가 사라졌을 때 한번 더 확인할 수 있도록 하였다.
success sign up
유효성 검사에 통과해 회원가입이 완료되면 성공을 알리는 모달이 발생한다.
확인 / 닫기 버튼을 누르면 자동으로 main page인 'sign in' 버튼이 있는 화면으로 전환된다.
sign in
sign in function
const signIn = async () => {
try {
const response = await fetch("https://dummyjson.com/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: "kminchelle",
password: "0lelplR",
}),
});
if (!response.ok) {
console.log("failed sign in!🥲");
}
const result = await response.json();
setIsUser(result);
} catch (error) {
console.log("during sign in💀: ", error);
}
};
sign in 함수는 비동기와 에러 처리를 위하여 try
를 활용해 보았다. user에 대한 부분은 BE 없이 진행되는 프로젝트 이기 때문에 더미 데이터를 활용하였다.
move to Todo
const goToTodo = () => {
navigate("/todo");
window.location.reload();
};
useEffect(() => {
if (isUser && isUser.token) {
goToTodo();
}
}, [isUser]);
로그인이 완료되면 회원으 데이터를 state에 저장하고 저장된 데이터의 token을 확인하여 token을 보유하고 있을 경우 페이지가 useNavigate Hook을 활용하여 전환될 수 있도록 하였다. 이때 이동에 대한 부분을 useEffect로 비동기 처리하고, 'isUser state'가 변경될 때를 추적할 수 있도록 하여, '로그인 통신이 완료되면', 'token'을 확인하도록 구현하였다.
✅ check point !
- interface Props
setBoolean: (value: boolean) => void 형태 !- onChange / onBlur
- Object.values().every()
- typescript의 비동기/에러 처리:
const signIn = async() => { try{ //...code } }
- navigate와 useEffect를 활용하여 조건에 따른 화면 전환 처리
감사합니다. 이런 정보를 나눠주셔서 좋아요.