-
Notifications
You must be signed in to change notification settings - Fork 0
[4주차 기본, 심화]🍁 로그인/회원가입🍁 #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "words": ["signup", "mypage"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| module.exports = { | ||
| root: true, | ||
| env: { browser: true, es2020: true }, | ||
| extends: [ | ||
| "eslint:recommended", | ||
| "plugin:react/recommended", | ||
| "plugin:react/jsx-runtime", | ||
| "plugin:react-hooks/recommended", | ||
| "plugin:react/recommended", | ||
| ], | ||
| ignorePatterns: ["dist", ".eslintrc.cjs"], | ||
| parserOptions: { ecmaVersion: "latest", sourceType: "module" }, | ||
| settings: { react: { version: "18.2" } }, | ||
| plugins: ["react-refresh"], | ||
| // rules: { | ||
| // "react-refresh/only-export-components": [ | ||
| // "warn", | ||
| // { allowConstantExport: true }, | ||
| // ], | ||
| // }, | ||
| extends: ["eslint:recommended", "plugin:react/recommended"], | ||
| rules: { | ||
| "react/prop-types": "off", | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Logs | ||
| logs | ||
| *.log | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
| pnpm-debug.log* | ||
| lerna-debug.log* | ||
|
|
||
| node_modules | ||
| dist | ||
| dist-ssr | ||
| *.local | ||
|
|
||
| # Editor directories and files | ||
| .vscode/* | ||
| !.vscode/extensions.json | ||
| .idea | ||
| .DS_Store | ||
| .env | ||
| .env.local | ||
| .env.development.local | ||
| .env.test.local | ||
| .env.production.local | ||
| *.suo | ||
| *.ntvs* | ||
| *.njsproj | ||
| *.sln | ||
| *.sw? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # React + Vite | ||
|
|
||
| This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. | ||
|
|
||
| Currently, two official plugins are available: | ||
|
|
||
| - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh | ||
| - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="ko"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
|
|
||
| <style> | ||
| @import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+KR:wght@100;200;300;400;500;600;700&family=Noto+Sans+KR:wght@100;200;300;400;500;600;700;800;900&display=swap"); | ||
| </style> | ||
| <title>로그인/회원가입</title> | ||
| </head> | ||
| <body> | ||
| <div id="root"></div> | ||
| <script type="module" src="/src/main.jsx"></script> | ||
| </body> | ||
| </html> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| { | ||
| "name": "week4", | ||
| "private": true, | ||
| "version": "0.0.0", | ||
| "type": "module", | ||
| "scripts": { | ||
| "dev": "vite", | ||
| "build": "vite build", | ||
| "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", | ||
| "preview": "vite preview" | ||
| }, | ||
| "dependencies": { | ||
| "axios": "^1.6.2", | ||
| "react": "^18.2.0", | ||
| "react-dom": "^18.2.0", | ||
| "react-router-dom": "^6.18.0", | ||
| "styled-components": "^6.1.1", | ||
| "styled-reset": "^4.5.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/react": "^18.2.15", | ||
| "@types/react-dom": "^18.2.7", | ||
| "@vitejs/plugin-react": "^4.0.3", | ||
| "eslint": "^8.45.0", | ||
| "eslint-plugin-react": "^7.32.2", | ||
| "eslint-plugin-react-hooks": "^4.6.0", | ||
| "eslint-plugin-react-refresh": "^0.4.3", | ||
| "vite": "^4.4.5" | ||
| } | ||
| } |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. react 프로젝트를 생성할 때마다 초기세팅의 일부로 이렇게 안쓰는 파일들은 지워주는걸 습관화하장!! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import Router from "./components/router"; | ||
|
|
||
| import React from "react"; | ||
| function App() { | ||
| return ( | ||
| <> | ||
| <Router /> | ||
| </> | ||
| ); | ||
| } | ||
|
|
||
| export default App; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import axios from "axios"; | ||
|
|
||
| const apiClient = axios.create({ | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| }, | ||
|
Comment on lines
+4
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. header까지 넣어서 만들었구나 ! 굿굿! |
||
| baseURL: import.meta.env.VITE_BASE_URL, | ||
| }); | ||
|
|
||
| export default apiClient; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import styled from "styled-components"; | ||
|
|
||
| const Title = styled.p` | ||
| color: black; | ||
| margin: 0.5rem 0; | ||
| font-size: 1.2rem; | ||
| font-weight: 600; | ||
| `; | ||
| export default Title; |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 유의해야할 점이! 리액트에서는 컴포넌트명을 파스칼케이스로 작성해줘야 리액트라 아~ 이게 컴포넌트구나! 하고 잘 알아먹느납니다 ㅎㅎ 따라서 일반 리액트 컴포넌트나 스타일드 컴포넌트 모두 꼭 대문자로 시작하는 것 잊지 말아요!
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 문법이니까 꼭 지키기! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import styled from "styled-components"; | ||
|
|
||
| const contentBox = styled.section` | ||
| display: grid; | ||
| place-items: center; | ||
| width: 30rem; | ||
| padding: 2.5rem; | ||
| background-color: ${({ theme }) => theme.white}; | ||
| grid-gap: 0.3rem; | ||
| position: absolute; | ||
| left: 50%; | ||
| top: 45%; | ||
| transform: translate(-50%, -50%); | ||
| border-radius: 1.3rem; | ||
| box-shadow: 5px 5px 5px lightgray; | ||
| `; | ||
| export default contentBox; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import styled from "styled-components"; | ||
|
|
||
| const Main = styled.button` | ||
| width: 25rem; | ||
| height: 2.5rem; | ||
| font-size: 0.9rem; | ||
| font-weight: 500; | ||
| border-style: none; | ||
| border-radius: 0.4rem; | ||
| background-color: ${({ theme }) => theme.yellow}; | ||
| cursor: pointer; | ||
| `; | ||
|
|
||
| const Secondary = styled.button` | ||
| width: 25rem; | ||
| height: 2.5rem; | ||
| font-size: 0.9rem; | ||
| font-weight: 500; | ||
| font-color: ${({ theme }) => theme.gray2}; | ||
| border-style: none; | ||
| border-radius: 0.4rem; | ||
| background-color: ${({ theme }) => theme.gray1}; | ||
| cursor: pointer; | ||
| `; | ||
|
|
||
| const Cta = { Main, Secondary }; | ||
| export default Cta; | ||
|
Comment on lines
+26
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상수를 export할 때는 대문자로 해줍시당 ! const CTA = { Main, Secondary };
export default CTA;There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 밑에 보다가 첨언하러 다시 올라왔어요 ! 코드 다시 보니깐 스타일에서 로그인인지 회원가입인지에 따라서 스타일링을 다르게 해주려고 서로 다른 버튼 컴포넌트를 만든 거였더라구요 ! styled-component에서도 동적 스타일링을 할 수 있답니다 ? prop을 전달해주어서 prop값에 따른 조건부 스타일링을 할 수 있어요 ! // login.jsx
// 로그인 버튼일 경우
<Main $login={true} >로그인</Main>
// 회원가입 버튼일 경우
<Main $login={false} >로그인</Main>
// �cta.jsx
const Main = styeld.div`
...
font-color: ${({ $login, theme }) => ($login ? theme.yellow : theme.gray2)};
`이렇게 조건부 스타일링을 한다면 중복되는 코드를 줄이고, 하나의 버튼 컴포넌트로 렌더링할 수 있겠죠? +) 변수 이름은 그 의미를 담고 있으면 좋아요 ! Main, Secondary보다는 LoginBtn, SignupBtn으로 짓는게 더 가독성 있겠죠 ? 💫 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞아요! css 에서는 저렇게 변경되는 state의 값에 따라 동적으로 조건부 렌더링을 해주기 위해 styled components 부분에 삼항 조건 연산자를 사용하는 경우도 꽤 자주 있답니다!!
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아니 앙큼토끼 서진언니 리뷰 폼 모야,, 앞으로 나아갈 방향성까지 조언해주는 금잔디가 있따,,? 나였으면 광광 울어따 (´。_。`) |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import styled from "styled-components"; | ||
|
|
||
| const info = styled.div` | ||
| height: 2rem; | ||
| transform: translate(0, -50%); | ||
| height: 5rem; | ||
| width: 9rem; | ||
| margin: 4rem 2rem; | ||
| display: grid; | ||
| grid-gap: 0.5rem; | ||
|
|
||
| & > p { | ||
| background-color: ${({ theme }) => theme.gray1}; | ||
| line-height: 2.5rem; | ||
| padding-left: 0.6rem; | ||
| font-weight: 500; | ||
| border-radius: 0.4rem; | ||
| } | ||
| `; | ||
|
|
||
| export default info; |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. props를 먼저 받아서 거치지 않고, 곧바로 곧바로 구조분해하는 방식 너무 좋아요! 👍 💯 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| import styled from "styled-components"; | ||
| import React from "react"; | ||
|
|
||
| const LoginForm = ({ idValue, setIdValue, pwValue, setPwValue }) => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 파일명이랑 컴포넌트 명을 맞추어주면 좋아요 !
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헤헤 요거 나도 리뷰 받았던 거 ! 그리구 파일명이랑 컴포넌트명을 동일하게 맞춰줌으로써 |
||
| return ( | ||
| <> | ||
| <Input> | ||
| <Wrapper> | ||
| <Name>ID</Name> | ||
| <Textholder | ||
| type="text" | ||
| placeholder="아이디를 입력하세요" | ||
| value={idValue} | ||
| onChange={(e) => setIdValue(e.target.value)} | ||
| ></Textholder> | ||
| </Wrapper> | ||
|
Comment on lines
+8
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이부분도 반복되는 걸 보니 내부 텍스트 따로 배열로 관리하고 전체적인 html 구조는 공통 컴포넌트로 분리하여 재사용하기 딱 좋아보이네요!! 🥺😎 |
||
| <Wrapper> | ||
| <Name>비밀번호</Name> | ||
| <Textholder | ||
| type="text" | ||
| placeholder="비밀번호를 입력하세요" | ||
| value={pwValue} | ||
| onChange={(e) => setPwValue(e.target.value)} | ||
| ></Textholder> | ||
| </Wrapper> | ||
| </Input> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
| const SignForm = ({ | ||
| username, | ||
| password, | ||
| passwordCheck, | ||
| nickname, | ||
| setUsername, | ||
| setPassword, | ||
| setPasswordCheck, | ||
| setNickname, | ||
| doubleCheck, | ||
| isExist, | ||
| isClicked, | ||
| setIsClicked, | ||
| }) => { | ||
| return ( | ||
| <> | ||
| <Input> | ||
| <Wrapper> | ||
| <Name>ID</Name> | ||
| <ShortTextholder | ||
| type="text" | ||
| placeholder="아이디를 입력하세요" | ||
| value={username} | ||
| onChange={(e) => setUsername(e.target.value)} | ||
| ></ShortTextholder>{" "} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요기 뒤에 {" "} 는 뭘까요? 공백 ?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저 공백이, vscode에서 태그들 내부에 실수로 공백이 포함된 채로 구현하게 되면, 자동 줄 맞춤이 될 때 저렇게 |
||
| <Btn | ||
| type="button" | ||
| onClick={() => { | ||
| doubleCheck(); | ||
| setIsClicked(true); | ||
| }} | ||
| isExist={isExist} // isExist 값을 전달 | ||
| isClicked={isClicked} // isClicked 값을 전달 | ||
| > | ||
| 중복확인 | ||
| </Btn> | ||
| </Wrapper> | ||
| <Wrapper> | ||
| <Name>비밀번호</Name> | ||
| <Textholder | ||
| type="text" | ||
| placeholder="비밀번호를 입력하세요" | ||
| value={password} | ||
| onChange={(e) => setPassword(e.target.value)} | ||
| ></Textholder> | ||
| </Wrapper> | ||
| <Wrapper> | ||
| <Name>비밀번호 확인</Name> | ||
| <Textholder | ||
| type="text" | ||
| placeholder="비밀번호를 다시 한번 입력해주세요" | ||
| value={passwordCheck} | ||
| onChange={(e) => setPasswordCheck(e.target.value)} | ||
| ></Textholder> | ||
| </Wrapper> | ||
| <Wrapper> | ||
| <Name>닉네임</Name> | ||
| <Textholder | ||
| type="text" | ||
| placeholder="닉네임을 입력해주세요" | ||
| value={nickname} | ||
| onChange={(e) => setNickname(e.target.value)} | ||
| ></Textholder> | ||
| </Wrapper> | ||
| </Input> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
| const Input = styled.section` | ||
| margin: 1rem 0; | ||
| `; | ||
| const Wrapper = styled.div` | ||
| display: flex; | ||
| margin: 0.5rem 0; | ||
| `; | ||
| const Name = styled.p` | ||
| color: ${({ theme }) => theme.black}; | ||
| font-weight: 500; | ||
| width: 6.5rem; | ||
| height: 2.5rem; | ||
| line-height: 2.5rem; | ||
| `; | ||
| const Textholder = styled.input` | ||
| background-color: ${({ theme }) => theme.gray1}; | ||
| color: grey; | ||
| height: 2.5rem; | ||
| width: 17rem; | ||
| border-style: none; | ||
| border-radius: 0.4rem; | ||
| padding-left: 1rem; | ||
|
|
||
| &::placeholder { | ||
| color: ${({ theme }) => theme.gray2}; | ||
| } | ||
| `; | ||
| const ShortTextholder = styled.input` | ||
| background-color: ${({ theme }) => theme.gray1}; | ||
| height: 2.5rem; | ||
| width: 12.5rem; | ||
| border-style: none; | ||
| border-radius: 0.4rem; | ||
| padding-left: 1rem; | ||
|
|
||
| &::placeholder { | ||
| color: ${({ theme }) => theme.gray2}; | ||
| } | ||
| `; | ||
|
|
||
| const Btn = styled.button` | ||
| background-color: ${({ theme, isExist, isClicked }) => { | ||
| if (isClicked === true) { | ||
| return isExist ? theme.red50 : theme.blue50; | ||
| } else if (isClicked === false) { | ||
| return theme.gray2; | ||
| } else { | ||
| return theme.gray2; | ||
| } | ||
| }}; | ||
|
|
||
| font-weight: 500; | ||
| border-style: none; | ||
| height: 2.5rem; | ||
| width: 4rem; | ||
| margin-left: 0.5rem; | ||
| border-style: none; | ||
| border-radius: 0.4rem; | ||
| cursor: pointer; | ||
| `; | ||
|
|
||
| const inputForm = { | ||
| LoginForm, | ||
| SignForm, | ||
| }; | ||
|
|
||
| export default inputForm; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저도 재훈오빠한테 들은 건데 @import는 성능 문제가 있을 수 있다고 하더라구요 ?
https://webclub.tistory.com/127
ㄴ 위에는 관련 링크입니다 !
합세 때도 글로벌 스타일 안에 @import를 하니까 warning이 났어서 저는
link태그를 이용했던 기억이,, 민서도 참고하면 좋을 것 같아요 ! !!