로그인 페이지 만들기

김지원·2020년 11월 17일
0

React

목록 보기
17/31

로그인 화면

메인 화면

맨처음에 내가 짠 코드들

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이란??

  1. 객체는 속성을 자유로이 변경할 수 있는데 반해, enum의 속성은 변경할 수 없습니다.
  2. 객체의 속성은 리터럴의 타입이 아니라 그보다 넓은 타입으로 타입 추론이 이루어집니다. enum은 항상 리터럴 타입이 사용됩니다.
  3. 객체의 속성 값으로는 JavaScript가 허용하는 모든 값이 올 수 있지만, 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문 조건문 중복되지 않게 하기

0개의 댓글

관련 채용 정보