foundation 기간이나 1차프로젝트 기간동안 사실상 로그인, 회원가입 기능은 거의 안해봐서 이번에 해보고 싶었다
1차프로젝트와는 다르게 2차 프로젝트에서는
function형 컴포넌트 및 styled-component를 이용했다!
// 로그인페이지 전체 레이아웃
<Whole>
<Logo>
<img src="./images/logo.png" alt="제발나와라" />
</Logo>
<LoginContainer>
<Title>로그인</Title>
{LoginDatas.map((LoginData, idx) => {
return <LoginInput key={idx} data={LoginData} />;
})}
<Btn
backColor="red"
textColor="white"
disabled={!check}
onClick={() => handleBtn()} >
로그인
</Btn>
<Help>
<a href="https://www.netflix.com/kr/LoginHelp">
도움이 필요하신가요?
</a>
</Help>
<Footer>
<Btn backColor="transparent" onClick={handleKakao}>
<img src="./images/kakaoBtn.png" alt="kakaoBtn" />
</Btn>
<p>
Flix 회원이 아니신가요?{" "}
<White onClick={() => history.push("/signup")}>
지금 가입하세요
</White>
</p>
<p>이 페이지에 안들어가면 후회하실겁니다!</p>
</Footer>
</LoginContainer>
</Whole>
이렇게 보면 태그들의 형태가 모두 심상치 않은데, 그 이유가 바로 styled-component를 사용했기 때문이다
$ npm install styled-component
import styled from "styled-components";
styled
+ .
+ 지정하고 싶은 태그이름
[const Whole = styled.div``]
으로 적어주었다const Whole = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
background-image: url("https://images.unsplash.com/photo-1545630478-cf62cdd247d1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MjR8fG1vdmllc3xlbnwwfHwwfHw%3D&auto=format&fit=crop&w=800&q=60");
`;
내용 자체는 잘 안보이겠지만
Login 컴포넌트 내부에서 사용하는 styled-component
자체가 적지 않기 때문에
만약 컴포넌트를 위에 선언하다보면 rendering되는 중요한 부분을 확인하기 힘들 것이다
// 배열 LoginDatas
const LoginDatas = [
{
name: userEmail,
title: "이메일주소",
type: "email",
validation: emailCheck,
inputAlert: "정확한 이메일 주소으로 입력해주세요.",
setName: setUserEmail
}, {
name: userPw,
title: "비밀번호",
type: "password",
validation: pwCheck,
inputAlert: "8자 이상 영문 대 소문자, 숫자, 특수문자를 사용하세요.",
setName: setUserPw
}
];
// 아이디, 비밀번호 입력하는 Input창
{LoginDatas.map((LoginData, idx) => {
return <LoginInput key={idx} data={LoginData} />;
})}
// 자식 컴포넌트인 LoginInput.js
const { name, title, type, validation,
inputAlert, setName }= props.data;
return (
<InputContainer>
<PlaceHolder>{title}</PlaceHolder>
<Input name={name} type={type}
onChange={e => setName(e.target.value)} />
{validation && <InputAlert>{inputAlert}</InputAlert>}
</InputContainer>
);
배열 LoginDatas에서 map()함수를 이용해서 각각의 LoginInput 컴포넌트 생성
{LoginDatas.map((LoginData, idx) => { return <LoginInput key={idx} data={LoginData} />; })}
이전의 class형 컴포넌트에서 자식 컴포넌트에게 props를 전달했을 때
자식컴포넌트에서는 this.props
로 확인했어야 했지만,
이번의 function형 컴포넌트에서 자식 컴포넌트에게 props를 전달했을 때
자식컴포넌트에서는 props.data
로 확인한다
const handleBtn = () => {
fetch("http://10.58.7.101:8000/users/sign-in", {
method: "POST",
body: JSON.stringify({
email: userEmail,
password: userPw,
signup_type: "flix"})
})
.then((res) => res.json())
.then((result) => {
if (result.message === "LOGIN_SUCCESS") {
alert(`Flix의 재미를 느껴보세요!`);
localStorage.setItem("token", result.token);
history.push("/");
} else {
alert("이메일 및 비밀번호를 올바르게 기입해주세요.");
}
});
};
<Btn
backColor="red"
textColor="white"
disabled={!check}
onClick={() => handleBtn()}
>
로그인
</Btn>;
로그인버튼이 눌렸을 때 handleBtn 함수가 실행되는데
사실 이렇게 함수 하나만 호출하는 거면 이런식으로 작성하는 게 더 깔끔해 보인다
onClick={handleBtn}
// fetch() 함수
fetch("http://10.58.7.101:8000/users/sign-in", {
method: "POST",
body: JSON.stringify({
email: userEmail,
password: userPw,
signup_type: "flix"})
})
http request 구조
이 블로그를 참고하면 좋을 것같다
.then((res) => res.json())
.then((result) => {
if (result.message === "LOGIN_SUCCESS") {
alert(`Flix의 재미를 느껴보세요!`);
localStorage.setItem("token", result.token);
history.push("/");
} else {
alert("이메일 및 비밀번호를 올바르게 기입해주세요.");
}
});
this.props.history.push()
메서드를 사용할 수 없어서 아래와 같은방법으로 페이지 이동 로직을 구현했다import { useHistory } from "react-router-dom";
const history = useHistory();
history.push("/");
react-router-dom 패키지에서 useHistory() 메서드를 import한 다음
useHistory() 메서드를 history 라고 지정해서
history.push() 메서드를 사용했다
react-router-dom의 Hook 더 알아보기
이 블로그를 참고해보자!