Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions week4_2/.cspell.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"words": ["signup", "mypage"]
}
25 changes: 25 additions & 0 deletions week4_2/.eslintrc.cjs
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",
},
};
29 changes: 29 additions & 0 deletions week4_2/.gitignore
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?
8 changes: 8 additions & 0 deletions week4_2/README.md
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
17 changes: 17 additions & 0 deletions week4_2/index.html
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");

Copy link
Copy Markdown
Member

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 태그를 이용했던 기억이,, 민서도 참고하면 좋을 것 같아요 ! !!

</style>
<title>로그인/회원가입</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
30 changes: 30 additions & 0 deletions week4_2/package.json
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"
}
}
1 change: 1 addition & 0 deletions week4_2/public/vite.svg

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react 프로젝트를 생성할 때마다 초기세팅의 일부로 이렇게 안쓰는 파일들은 지워주는걸 습관화하장!!

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added week4_2/src/App.css
Empty file.
12 changes: 12 additions & 0 deletions week4_2/src/App.jsx
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;
10 changes: 10 additions & 0 deletions week4_2/src/api/axios.js
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

header까지 넣어서 만들었구나 ! 굿굿!
이번 과제에서는 header를 바꿀일이 없으니 이렇게 만들어서 export하는 것 좋네용 !

baseURL: import.meta.env.VITE_BASE_URL,
});

export default apiClient;
Binary file added week4_2/src/assets/profile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions week4_2/src/assets/react.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions week4_2/src/components/Title.jsx
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;
17 changes: 17 additions & 0 deletions week4_2/src/components/contentBox.jsx

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

유의해야할 점이! 리액트에서는 컴포넌트명을 파스칼케이스로 작성해줘야 리액트라 아~ 이게 컴포넌트구나! 하고 잘 알아먹느납니다 ㅎㅎ 따라서 일반 리액트 컴포넌트나 스타일드 컴포넌트 모두 꼭 대문자로 시작하는 것 잊지 말아요!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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;
27 changes: 27 additions & 0 deletions week4_2/src/components/cta.jsx
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상수를 export할 때는 대문자로 해줍시당 !

const CTA = { Main, Secondary };
export default CTA;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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으로 짓는게 더 가독성 있겠죠 ? 💫

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요! css 에서는 저렇게 변경되는 state의 값에 따라 동적으로 조건부 렌더링을 해주기 위해 styled components 부분에 삼항 조건 연산자를 사용하는 경우도 꽤 자주 있답니다!!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아니 앙큼토끼 서진언니 리뷰 폼 모야,, 앞으로 나아갈 방향성까지 조언해주는 금잔디가 있따,,? 나였으면 광광 울어따 (´。_。`)

21 changes: 21 additions & 0 deletions week4_2/src/components/info.jsx
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;
166 changes: 166 additions & 0 deletions week4_2/src/components/inputForm.jsx

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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 }) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

파일명이랑 컴포넌트 명을 맞추어주면 좋아요 !
지금 보면 inputForm 파일 안에 로그인 컴포넌트랑 회원가입 컴포넌트가 들어있는데, 하나의 파일에는 하나의 컴포넌트만 넣어두는게 좋답니다 !
그 말은 즉 로그인과 회원가입을 각자 다른 파일으로 분리하여 작성할 수 있다는 거겠죠 ? ☺️
로그인과 회원가입에서 각자 전달받는 prop도 다르기 때문에 분리하여 작성하면 가독성이 더 좋아질 거에요 ! 그리고 전달하는 prop들도 분리되어 데이터 전달 흐름도 개선할 수 있을 거에요 ! ㅎㅎ

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

헤헤 요거 나도 리뷰 받았던 거 ! 그리구 파일명이랑 컴포넌트명을 동일하게 맞춰줌으로써 rsc 단축키로 쉽게 코드 생성이 가능하다고 함니다 - ?!

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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>{" "}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요기 뒤에 {" "} 는 뭘까요? 공백 ?!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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;
Loading