로그인 화면
메인 화면
맨처음에 내가 짠 코드들
App.tsx 코드
import React, { useState } from "react";
import LoginPage from "./loginPage";
import MainPage from "./mainPage";
function App(props: any): JSX.Element {
const [mode, setMode] = useState("LOGIN");
const [data, setData] = useState("");
if (mode === "MAIN") return <MainPage setMode={setMode} props={data} />;
return <LoginPage setMode={setMode} setData={setData} />;
}
export default App;
LoginPage.tsx
import React, { useState } from "react";
import styled from "styled-components";
const LoginPage: any = (props: any) => {
const [id, setId] = useState("");
const [pwd, setPwd] = useState("");
const onChangeId = (e: React.ChangeEvent<HTMLInputElement>) => {
setId(e.currentTarget.value);
};
const onChangePwd = (e: React.ChangeEvent<HTMLInputElement>) => {
setPwd(e.currentTarget.value);
};
const onSubmit = () => {
if (id === "") {
alert("아이디를 입력해주세요");
} else if (pwd === "") {
alert("비밀번호를 입력해주세요");
} else if (pwd === "1234") {
alert(`${id} 님 환영합니다`);
props.setMode("MAIN");
props.setData(id);
} else if (pwd !== "1234") {
alert("비밀번호가 틀렸습니다.");
}
};
return (
<MyDiv>
<MyH1>PurpleCode</MyH1>
<form>
<MyUl>
<MyLi>
<MyLabel htmlFor="user_id">아이디:</MyLabel>
<InputDiv>
<MyInput
id="user_id"
value={id}
onChange={onChangeId}
placeholder="아이디를 입력해주세요"
required
/>
<hr />
</InputDiv>
</MyLi>
<MyLi>
<MyLabel htmlFor="user_pwd">비밀번호:</MyLabel>
<InputDiv>
<MyInput
id="user_pwd"
value={pwd}
onChange={onChangePwd}
placeholder="비밀번호를 입력해주세요"
required
/>
<hr />
</InputDiv>
</MyLi>
</MyUl>
<SubmitInput type="submit" value="로그인" onClick={onSubmit} />
</form>
</MyDiv>
);
};
const MyDiv = styled.div`
padding: 0px;
text-align: center;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
`;
const MyH1 = styled.h1`
color: purple;
font-size: 6vw;
padding: 0px;
`;
const MyUl = styled.ul`
list-style: none;
padding: 0px;
`;
const MyLi = styled.li`
width: 28vw;
display: flex;
align-items: center;
font-size: 1.6vw;
margin 0 auto;
`;
const InputDiv = styled.div`
width: 17vw;
`;
const MyInput = styled.input`
:focus {
outline: none;
}
border: none;
::placeholder {
color: gray;
font-size: 1vw;
}
`;
const MyLabel = styled.label`
margin-right: 1vw;
height: 5vh;
`;
const SubmitInput = styled.input`
background-color: purple;
border: none;
color: white;
width: 10vw;
height: 5vh;
text-decoration: none;
text-align: center;
font-size: 1vw;
`;
export default LoginPage;
MainPage.tsx
import React, { useState } from "react";
import styled from "styled-components";
const MainPage: any = (props: any) => {
const onclick = () => {
alert("로그아웃 합니다.");
props.setMode("LOGIN");
};
return (
<div>
<MainUl>
<LogoLi>PurpleCode</LogoLi>
<NavDiv>
<MainLi>{props.props}님</MainLi>
<MainLi>
<SubmitInput type="submit" value="로그아웃" onClick={onclick} />
</MainLi>
</NavDiv>
</MainUl>
<MainP>{props.props}님 환영합니다.</MainP>
</div>
);
};
const MainUl = styled.ul`
padding: 0px;
list-style: none;
display: flex;
justify-content: space-between;
`;
const NavDiv = styled.div`
display: flex;
`;
const LogoLi = styled.li`
color: purple;
font-weight: bold;
font-size: 3vw;
`;
const MainLi = styled.li`
margin: 0vw 1vw;
`;
const MainP = styled.p`
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
`;
const SubmitInput = styled.input`
background-color: purple;
border: none;
color: white;
width: 10vw;
height: 5vh;
text-decoration: none;
text-align: center;
font-size: 1vw;
`;
export default MainPage;
string으로 mode를 설정해주는 것보다는 enum 을 사용하기
이전 App.tsx
const [mode, setMode] = useState("LOGIN");
수정한 App.tsx
enum Mode {
LOGIN =1,
MAIN = 2
}
const App: React.FC = () => {
const[mode,setMode] = useState(Mode.LOGIN);
...
+ App.tsx는 props 받는 것이 없기 때문에 잘못써줬던 function App(props: any)
도 지움
enum이란??
정리
같은 ‘종류’를 나타내는 여러 개의 숫자 혹은 문자열을 다뤄야 하는데, 각각 적당한 이름을 붙여서 코드의 가독성을 높이고 싶다면 enum을 사용하세요.
적절한 변수명 사용하기
이전 App.tsx
const [data, setData] = useState("");
if (mode === "MAIN")
return <MainPage setMode={setMode} props={data} />;
수정한 App.tsx
const [id, setId] = useState("");
if (mode === Mode.MAIN) return <MainPage id={id}
...
id를 받아오는데 사용했던 data는 무엇을 받아오는지 알수 없으므로 id로 바꾸어주고 props를 줄때 props를 쓰면
props {
props: ...
}
이런 식으로 되므로 절대 쓰지 않기!
props로 setMode를 주기보다는
onSetMainMode
함수를 만들어 전달해 mode를 변경해주면
MainPage.tsx에서 onClick했을 때 alert밖에 안남으므로onLogOut
함수를 만들어 전달해주기
:any 대신 타입 지정해주기!
props 타입은 interface 사용해서 지정하기
props라고 전달해주기보다는 비구조화할당을 사용해서
{ id, onLogOut } 이런식으로 써주기!
이전 App.tsx
const [mode, setMode] = useState("LOGIN");
if (mode === "MAIN")
return <MainPage setMode={setMode} props={data} />;
이전 MainPage.tsx
const MainPage: any = (props: any) => {
const onclick = () => {
alert("로그아웃 합니다.");
props.setMode("LOGIN");
};
수정한 App.tsx
const onLogOut = () => {
alert("로그아웃 합니다.");
setMode(Mode.LOGIN);
};
if (mode === Mode.MAIN)
return <MainPage id={id} onLogOut={onLogOut} />;
수정한 MainPage.tsx
interface MainPageProps{
id: string,
onLogOut: () => void;
}
const MainPage: React.FC <MainPageProps>
= ({id, onLogOut}) => {
return (
<div>
<MainUl>
<LogoLi>PurpleCode</LogoLi>
<NavDiv>
<MainLi>{id}님</MainLi>
<MainLi>
<SubmitInput type="submit"
value="로그아웃"
onClick={onLogOut} />
</MainLi>
</NavDiv>
</MainUl>
<MainP>{id}님 환영합니다.</MainP>
</div>
);
};
onLogIn
함수를 만들어 props로 전달해주기
props와 return 타입 지정해주기
이전 App.tsx
return <LoginPage
setMode={setMode}
setData={setData} />;
이전 LoginPage.tsx
const LoginPage: any = (props: any) => {
...
else if (pwd === "1234") {
alert(`${id} 님 환영합니다`);
props.setMode("MAIN");
props.setData(id);
}
...
수정한 App.tsx
const onLogIn = (userId: string) => {
alert(`${userId} 님 환영합니다`);
setMode(Mode.MAIN);
setId(userId);
};
...
return <LoginPage onLogIn={onLogIn} />;
수정한 LoginPage.tsx
interface LoginPageProps {
onLogIn: (userId: string) => void;
}
const LoginPage: React.FC<LoginPageProps> = ({ onLogIn })
=> {
...
else if (pwd === "1234") {
onLogIn(id);
}
...
usecallback
으로 렌더링 성능 최적화 하기
이전 LoginPage.tsx
const onChangeId=(e: React.ChangeEvent<HTMLInputElement>)
=> {
setId(e.currentTarget.value);
};
const onChangePwd=(e: React.ChangeEvent<HTMLInputElement>)
=> {
setPwd(e.currentTarget.value);
};
수정한 LoginPage.tsx
const onChangeId=useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setId(e.currentTarget.value);
}, []);
const onChangePwd = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setPwd(e.currentTarget.value);
}, []);
공백 입력시 alert 띄우기 추가
수정한 LoginPage.tsx
const onChangeId = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
const blank = /\s/;
if (blank.test(e.currentTarget.value) === true) {
alert("공백은 사용할 수 없습니다.");
return;
}
setId(e.currentTarget.value);
}, []);
test()
: 찾는 문자열이 들어있는지 아닌지를 알려준다. 찾으려는 문자가 들어있으면 결과는 "true"이다.
styled-comonents
따로 디렉토리에 넣기
Loginstyle.ts
import styled from "styled-components";
export const MyDiv = styled.div`
padding: 0px;
text-align: center;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
`;
export const MyH1 = styled.h1`
color: purple;
font-size: 6vw;
padding: 0px;
`;
export const MyUl = styled.ul`
list-style: none;
padding: 0px;
`;
export const MyLi = styled.li`
width: 28vw;
display: flex;
align-items: center;
font-size: 1.6vw;
margin 0 auto;
`;
export const InputDiv = styled.div`
width: 17vw;
`;
export const MyInput = styled.input`
:focus {
outline: none;
}
border: none;
::placeholder {
color: gray;
font-size: 1vw;
}
`;
export const MyLabel = styled.label`
margin-right: 1vw;
height: 5vh;
`;
export const SubmitInput = styled.input`
background-color: purple;
border: none;
color: white;
width: 10vw;
height: 5vh;
text-decoration: none;
text-align: center;
font-size: 1vw;
`;
Mainstyle.ts
import styled from "styled-components";
export const MainUl = styled.ul`
padding: 0px;
list-style: none;
display: flex;
justify-content: space-between;
`;
export const NavDiv = styled.div`
display: flex;
`;
export const LogoLi = styled.li`
color: purple;
font-weight: bold;
font-size: 3vw;
`;
export const MainLi = styled.li`
margin: 0vw 1vw;
`;
export const MainP = styled.p`
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
`;
export const SubmitInput = styled.input`
background-color: purple;
border: none;
color: white;
width: 10vw;
height: 5vh;
text-decoration: none;
text-align: center;
font-size: 1vw;
`;
1차 수정한 코드들
App.tsx
import React, { useState } from "react";
import LoginPage from "./LoginPage/LoginPage";
import MainPage from "./MainPage/MainPage";
enum Mode {
LOGIN = 1,
MAIN = 2,
}
const App: React.FC = () => {
const [mode, setMode] = useState(Mode.LOGIN);
const [id, setId] = useState("");
const onLogIn = (userId: string) => {
alert(`${userId} 님 환영합니다`);
setMode(Mode.MAIN);
setId(userId);
};
const onLogOut = () => {
alert("로그아웃 합니다.");
setMode(Mode.LOGIN);
};
if (mode === Mode.MAIN) return <MainPage id={id} onLogOut={onLogOut} />;
return <LoginPage onLogIn={onLogIn} />;
};
export default App;
LoginPage.tsx
import React, { useCallback, useState } from "react";
import {
MyDiv,
MyH1,
MyUl,
MyLi,
InputDiv,
MyInput,
MyLabel,
SubmitInput,
} from "./Loginstyle";
interface LoginPageProps {
onLogIn: (userId: string) => void;
}
const LoginPage: React.FC<LoginPageProps> = ({ onLogIn }) => {
const [id, setId] = useState("");
const [pwd, setPwd] = useState("");
const onChangeId = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
const blank = /\s/;
if (blank.test(e.currentTarget.value) === true) {
alert("공백은 사용할 수 없습니다.");
return;
}
setId(e.currentTarget.value);
}, []);
const onChangePwd = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setPwd(e.currentTarget.value);
}, []);
const onSubmit = () => {
if (id === "") {
alert("아이디를 입력해주세요");
} else if (pwd === "") {
alert("비밀번호를 입력해주세요");
} else if (pwd === "1234") {
onLogIn(id);
} else if (pwd !== "1234") {
alert("비밀번호가 틀렸습니다.");
}
};
return (
<MyDiv>
<MyH1>PurpleCode</MyH1>
<form>
<MyUl>
<MyLi>
<MyLabel htmlFor="user_id">아이디:</MyLabel>
<InputDiv>
<MyInput
id="user_id"
value={id}
onChange={onChangeId}
placeholder="아이디를 입력해주세요"
required
/>
<hr />
</InputDiv>
</MyLi>
<MyLi>
<MyLabel htmlFor="user_pwd">비밀번호:</MyLabel>
<InputDiv>
<MyInput
id="user_pwd"
value={pwd}
onChange={onChangePwd}
placeholder="비밀번호를 입력해주세요"
required
/>
<hr />
</InputDiv>
</MyLi>
</MyUl>
<SubmitInput type="submit" value="로그인" onClick={onSubmit} />
</form>
</MyDiv>
);
};
MainPage.tsx
import React, { useState } from "react";
import {
MainLi,
SubmitInput,
LogoLi,
MainP,
MainUl,
NavDiv,
} from "./Mainstyle";
interface MainPageProps {
id: string;
onLogOut: () => void;
}
const MainPage: React.FC<MainPageProps> = ({ id, onLogOut }) => {
return (
<div>
<MainUl>
<LogoLi>PurpleCode</LogoLi>
<NavDiv>
<MainLi>{id}님</MainLi>
<MainLi>
<SubmitInput type="submit" value="로그아웃" onClick={onLogOut} />
</MainLi>
</NavDiv>
</MainUl>
<MainP>{id}님 환영합니다.</MainP>
</div>
);
};
export default MainPage;
함수는 하나의 역할을 하도록 나누기
로그인 체크 시 if문 조건문 중복되지 않게 하기