-
Notifications
You must be signed in to change notification settings - Fork 1
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
[ 4주차 기본/공유 과제 ] 보운이의 로그 #5
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,18 @@ | ||
module.exports = { | ||
root: true, | ||
env: { browser: true, es2020: true }, | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:@typescript-eslint/recommended', | ||
'plugin:react-hooks/recommended', | ||
], | ||
ignorePatterns: ['dist', '.eslintrc.cjs'], | ||
parser: '@typescript-eslint/parser', | ||
plugins: ['react-refresh'], | ||
rules: { | ||
'react-refresh/only-export-components': [ | ||
'warn', | ||
{ allowConstantExport: true }, | ||
], | ||
}, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# 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 | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"printWidth": 120, | ||
"tabWidth": 4, | ||
"semi": true, | ||
"singleQuote": true, | ||
"trailingComma": "es5", | ||
"requirePragma": false, | ||
"arrowParens": "always", | ||
"endOfLine": "auto", | ||
"arrayIndentation": "auto", | ||
"bracketSpacing": false | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# React + TypeScript + 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 | ||
|
||
## Expanding the ESLint configuration | ||
|
||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: | ||
|
||
- Configure the top-level `parserOptions` property like this: | ||
|
||
```js | ||
export default { | ||
// other rules... | ||
parserOptions: { | ||
ecmaVersion: 'latest', | ||
sourceType: 'module', | ||
project: ['./tsconfig.json', './tsconfig.node.json'], | ||
tsconfigRootDir: __dirname, | ||
}, | ||
} | ||
``` | ||
|
||
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` | ||
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` | ||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import globals from "globals"; | ||
import pluginJs from "@eslint/js"; | ||
import tseslint from "typescript-eslint"; | ||
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; | ||
|
||
|
||
export default [ | ||
{languageOptions: { globals: globals.browser }}, | ||
pluginJs.configs.recommended, | ||
...tseslint.configs.recommended, | ||
pluginReactConfig, | ||
]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!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" /> | ||
<title>보운이의 로그인</title> | ||
</head> | ||
<body style="margin: 0px; background-color: rgb(184, 202, 186)"> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
{ | ||
"name": "week4-login", | ||
"private": true, | ||
"version": "0.0.0", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "tsc && vite build", | ||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", | ||
"preview": "vite preview", | ||
"format": "prettier --write --cache ." | ||
}, | ||
"dependencies": { | ||
"@types/styled-components": "^5.1.34", | ||
"axios": "^1.6.8", | ||
"file-loader": "^6.2.0", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0", | ||
"react-player": "^2.16.0", | ||
"react-router-dom": "^6.23.0", | ||
"styled-components": "^6.1.10", | ||
"typescript-plugin-styled-components": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"@eslint/js": "^9.2.0", | ||
"@types/react": "^18.2.66", | ||
"@types/react-dom": "^18.2.22", | ||
"@types/react-router": "^5.1.20", | ||
"@types/react-router-dom": "^5.3.3", | ||
"@typescript-eslint/eslint-plugin": "^7.2.0", | ||
"@typescript-eslint/parser": "^7.8.0", | ||
"@vitejs/plugin-react-swc": "^3.5.0", | ||
"eslint": "^9.2.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-import-resolver-typescript": "^3.6.1", | ||
"eslint-plugin-import": "^2.29.1", | ||
"eslint-plugin-prettier": "^5.1.3", | ||
"eslint-plugin-react": "^7.34.1", | ||
"eslint-plugin-react-hooks": "^4.6.2", | ||
"eslint-plugin-react-refresh": "^0.4.6", | ||
"globals": "^15.1.0", | ||
"prettier": "^3.2.5", | ||
"typescript": "^5.2.2", | ||
"typescript-eslint": "^7.8.0", | ||
"vite": "^5.2.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import {Route, Routes} from 'react-router-dom'; | ||
import MainPage from './page/MainPage'; | ||
import LoginPage from './page/LoginPage'; | ||
import SignupPage from './page/SignupPage'; | ||
import MyPage from './page/MyPage'; | ||
|
||
function App() { | ||
return ( | ||
<Routes> | ||
<Route path="/" element={<MainPage />} /> | ||
<Route path="/:memberId" element={<MainPage />} /> | ||
<Route path="/login" element={<LoginPage />} /> | ||
<Route path="/signup" element={<SignupPage />} /> | ||
<Route path="/mypage/:memberId" element={<MyPage />} /> | ||
</Routes> | ||
); | ||
} | ||
|
||
export default App; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const BASE_URL = 'http://34.64.233.12:8080'; | ||
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. p5)base_url을 이렇게 빼서 사용할 수 도 있군여 ?! 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. p1: 서버 주소는 .env 파일로 빼주세요! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom/client'; | ||
import App from './App.tsx'; | ||
import {BrowserRouter} from 'react-router-dom'; | ||
|
||
ReactDOM.createRoot(document.getElementById('root')!).render( | ||
<BrowserRouter> | ||
<React.StrictMode> | ||
<App /> | ||
</React.StrictMode> | ||
</BrowserRouter> | ||
Comment on lines
+7
to
+11
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. p4: 일반적으로 애플리케이션의 모든 부분에 StricMode를 적용하기위해서 StricMode를 가장 바깥쪽으로 빼주는 것으로 알고 있습니다. |
||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import {Area, HelpP, IMG, Input, InputContaier, InputSort, MoveButton} from '../style/styleComponents'; | ||
import loginImg from '../assets/img2.jpg'; | ||
import {Link, useNavigate} from 'react-router-dom'; | ||
import {useState} from 'react'; | ||
import axios from 'axios'; | ||
import {BASE_URL} from '../assets/base-url'; | ||
|
||
export default function LoginPage() { | ||
const navi = useNavigate(); | ||
const [id, setId] = useState(''); | ||
const [pw, setPw] = useState(''); | ||
|
||
const handleLogin = async () => { | ||
if (id && pw) { | ||
//만약 모두가 값이 있다면 | ||
try { | ||
await axios | ||
.post(`${BASE_URL}/member/login`, { | ||
authenticationId: id, | ||
password: pw, | ||
}) | ||
Comment on lines
+1
to
+21
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. p5)저는 fetch를 사용했는데 axios를 많이들 사용했더라구여?! 사용하는 방법 배워갑니다~ 그리고 확실히 axios를 사용하면 형변환 할일이 없어 코드가 간결해지는 것 같아염 |
||
.then((res) => { | ||
//location Header에 있는 게 이거 맞나..? | ||
//useParam을 어떻게 활용하지....? | ||
const memberId = res.headers.location; | ||
console.log(memberId); | ||
//아 이걸 useParam써서 메인으로 보내자 | ||
Comment on lines
+23
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. p5: ㅋㅋㅋㅋ 생각의 흐름이 주석에 남아있는게 좋네요 ㅋㅋ console 만 지워주시면 좋을 것 같습니다. 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. p5: ㅋㅋㅋㅋ 너무 멋져요 |
||
|
||
alert(res.data.message); | ||
//to main page | ||
navi(`/${memberId}`); | ||
}) | ||
.catch((error) => alert(error.response.data.message)); | ||
} catch { | ||
//error | ||
} | ||
} | ||
}; | ||
|
||
return ( | ||
<Area> | ||
<h1>Login</h1> | ||
<IMG src={loginImg} alt="loginImg" /> | ||
<InputContaier> | ||
<InputSort>ID</InputSort> | ||
<div style={{width: '100%'}}> | ||
<Input | ||
onChange={(e) => setId(e.currentTarget.value)} | ||
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. p5: 저는 |
||
type="text" | ||
placeholder="아이디를 입력하세요" | ||
/> | ||
{!id && <HelpP>아이디를 입력하세요</HelpP>} | ||
Comment on lines
+45
to
+52
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. p4) 혹시 div style옆 width무슨 의미인지 설명해주실 수 있을까여?! 인라인스타일이면 담부터 지양하시는게 좋을 거같아여~ 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. pr에 작성해주신 고민이 이 부분이네요. 간단한 스타일의 경우 사실 styled component를 추가로 만드는 것이 비효율 적으로 보일 수는 있지만, 나중에 유지보수를 하거나 스타일을 변경해야 하는 상황을 생각해보면, 스타일 코드가 여기저기에 나뉘어져 있다면, 유지보수할 때의 난이도가 굉장히 올라간다고 생각합니다. 따라서 조금 비효율적으로 보일진 몰라도, styled component를 사용하는 프로젝트라면 모든 스타일을 styled로 주는 것이 좋을 것 같습니다. 태그이름은 개인적 규칙이나, 팀의 컨벤션에 맞게 작성하셔야하지만 PR에 물어보셔서 답변해드리자면 InputWrapper등의 이름으로 감싸주면 될 것 같습니다. 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. p5: 저도 위 생각에 동의합니다. 스타일 코드가 이렇게 나뉘어져있으면 유지보수가 힘들어 질 수 있어요! 아래 링크와 같이 본인 스스로의 규칙을 만들면 좋아요! 그리고 그 규칙들을 협업하는 팀원들과 공유한다면 더 좋을 것 같아요! |
||
</div> | ||
</InputContaier> | ||
<InputContaier> | ||
<InputSort>PW</InputSort> | ||
<div style={{width: '100%'}}> | ||
<Input | ||
onChange={(e) => setPw(e.currentTarget.value)} | ||
type="password" | ||
placeholder="비밀번호를 입력하세요" | ||
/> | ||
{!pw && <HelpP>비밀번호를 입력해주세요 제발</HelpP>} | ||
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. p5: pw state값에 따라 메시지 띄워주는거 좋네요! |
||
</div> | ||
</InputContaier> | ||
<div> | ||
<MoveButton onClick={handleLogin}>로그인</MoveButton> | ||
<Link to={'/signup'}> | ||
<MoveButton>회원가입</MoveButton> | ||
</Link> | ||
</div> | ||
</Area> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import {Link, useParams} from 'react-router-dom'; | ||
import {Header, MoveButton, Section} from '../style/styleComponents'; | ||
import ReactPlayer from 'react-player'; | ||
|
||
function MainPage() { | ||
const {memberId} = useParams<string>(); | ||
|
||
console.log(memberId); | ||
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. p4: 테스트 끝난 console.log는 삭제해주세요~ |
||
return ( | ||
<div> | ||
<Header>보운이의 로그인</Header> | ||
<Section> | ||
Comment on lines
+10
to
+12
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. p5: 가장 div가 딱히 스타일도 없고, 의미가 없는 태그라면, div대신 <></>로 감싸주는건 어떨까요? |
||
<ReactPlayer url={'/videos/고양이.mp4'} playing={true} loop={true} muted={true} /> | ||
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. p5: ReactPlayer사용해서 동영상 넣으셨군요 좋네요! |
||
<div> | ||
{memberId ? ( | ||
<Link to={`/mypage/${memberId}`}> | ||
<MoveButton>내 정보</MoveButton> | ||
</Link> | ||
) : ( | ||
<Link to={'/login'}> | ||
<MoveButton>로그인</MoveButton> | ||
</Link> | ||
)} | ||
<Link to={'/signup'}> | ||
<MoveButton>회원가입</MoveButton> | ||
</Link> | ||
</div> | ||
</Section> | ||
</div> | ||
); | ||
} | ||
|
||
export default MainPage; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import {useEffect, useState} from 'react'; | ||
import {Area, Info, MoveButton, OneLine, PwEditBtn, ShowORNot} from '../style/styleComponents'; | ||
import {Link, useParams} from 'react-router-dom'; | ||
import axios from 'axios'; | ||
import {BASE_URL} from '../assets/base-url'; | ||
import PwEditComp from './PwEditComp'; | ||
|
||
type Info = { | ||
id: string; | ||
nickname: string; | ||
phone: string; | ||
}; | ||
Comment on lines
+1
to
+12
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. p4)코드를 각각 구조에 맞게 잘 나누신 것 같아여 |
||
|
||
export default function MyPage() { | ||
const {memberId} = useParams<string>(); | ||
const [info, setInfo] = useState<Info>(); | ||
|
||
useEffect(() => { | ||
//memberId로 | ||
try { | ||
axios | ||
.get(`${BASE_URL}/member/info`, { | ||
headers: { | ||
memberId: memberId, | ||
}, | ||
}) | ||
.then((res) => { | ||
const myInfo: Info = { | ||
id: res.data.data.authenticationId, | ||
nickname: res.data.data.nickname, | ||
phone: res.data.data.phone, | ||
}; | ||
setInfo(myInfo); | ||
console.log(myInfo); | ||
}) | ||
.catch((error) => { | ||
alert(error.response.data.message); | ||
console.log(error); | ||
}); | ||
} catch { | ||
//error | ||
} | ||
}, []); | ||
|
||
function handleShowPw() { | ||
const nowState = document.getElementById('showornot')!.style.visibility; | ||
if (nowState == 'hidden') { | ||
//숨겨뒀다가 열려고 누름 -> 보여야함 | ||
document.getElementById('showornot')!.style.visibility = 'visible'; | ||
} else { | ||
document.getElementById('showornot')!.style.visibility = 'hidden'; | ||
} | ||
} | ||
|
||
Comment on lines
+45
to
+54
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. p4) 비밀번호 여닫는 폼을 이렇게도 구현할 수 있군여 배워갑니다. 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. P3: 리액트에서 DOM에 직접접근하여 조작하는 것은 권장되지 않는 방식입니다. state값을 styled 컴포넌트에 인자로 전달에서 인자에 따라 스타일 값을 바꿔주거나, DOM을 직접 조작해야한다면 useRef를 사용하여 조작하는 것이 나을 것 같습니다. 혹시 더 좋은 방법이 있다면 알려주시면 감사하겠습니다. |
||
return ( | ||
<> | ||
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. 여기도 빈 태그 빼면 좋을 것 같아요! |
||
<Area> | ||
<h1>마이페이지</h1> | ||
<section> | ||
<OneLine> | ||
<Info>ID</Info> | ||
<Info>{info?.id}</Info> | ||
</OneLine> | ||
<OneLine> | ||
<Info>닉네임</Info> | ||
<Info>{info?.nickname}</Info> | ||
</OneLine> | ||
<OneLine> | ||
<Info>전화번호</Info> | ||
<Info>{info?.phone}</Info> | ||
</OneLine> | ||
</section> | ||
<section> | ||
<div style={{display: 'flex', gap: '1rem'}}> | ||
<p>비밀번호 변경</p> | ||
<PwEditBtn onClick={handleShowPw}>{'>'}</PwEditBtn> | ||
</div> | ||
<ShowORNot id="showornot"> | ||
<PwEditComp props={memberId!} /> | ||
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. p3: 컴포넌트에 전달하는 인자이름을 props로 하기보다는 변수에 맞는 변수명으로 넘겨주는 것이 좋을것 같습니다! 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. p5: memberId뒤에 ! 를 붙인 이유가 있으실까요? 에러가 나서 그냥 추가하신 거라면, 사용하는 쪽에서 null 체크를 하는 것으로는 해결이 안되나요? |
||
</ShowORNot> | ||
</section> | ||
<Link to={`/${memberId}`}> | ||
<MoveButton>홈으로</MoveButton> | ||
</Link> | ||
</Area> | ||
</> | ||
); | ||
} |
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.
p4: 여기 글로벌 스타일로 빼면 좋을 것 같아요!