Skip to content

Commit

Permalink
Merge pull request #51 from KOOMINSEOK/main
Browse files Browse the repository at this point in the history
[4주차/민] 키워드 제출합니다
  • Loading branch information
KOOMINSEOK authored Nov 8, 2024
2 parents 6d3db57 + 37762a1 commit 37de24c
Show file tree
Hide file tree
Showing 43 changed files with 19,924 additions and 0 deletions.
438 changes: 438 additions & 0 deletions keyword/chapter04/keyword.md

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions keyword/chapter05/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
- useRef 🍠

함수형 컴포넌트 내에서 DOM 요소나 다른 React 요소를 참조하기 위해 사용되는 Hook

- 기본 형태

```jsx
const 변수명 = useRef(초기값);
```

결과값으로 초기값 {current : 초기값}을 지닌 객체가 반환

- 특징
1. 컴포넌트가 계속해서 **렌더링이 되어도** 컴포넌트가 언마운드되기 전까지는 **값을 그대로 유지**
2. **currnet 속성은 값을 변경해도** 상태를 변경할 때 처럼 **React 컴포넌트가 재렌더링 되지 않음 → 성능향상**
- useRef를 사용하는 경우
1. 컴포넌트의 렌더링과 관련이 없는 값들을 저장할 때
2. DOM 요소에 대한 참조를 저장할 때
3. 렌더링 과정에서 값이 변경되어도 다시 렌더링되지 않아도 되는 경우

- input의 주요 프로퍼티 🍠
- 아래 내용 이외에, 자주 사용하는 프로퍼티가 있으면 추가로 더 정리해주세요! 🍠
- **pattern**: 특정 정규표현식을 적용하여 입력 값을 검사함

```html

<input type="text" pattern="[A-Za-z]{3,}" title="Only letters allowed" />

```

- **autofocus**: 페이지 로드 시 해당 입력 필드에 자동으로 포커스를 설정

```html

<input type="text" autofocus />

```

- **size**: 입력 필드의 너비(글자 수 기준)를 지정

```html

<input type="text" size="20" />

```
33 changes: 33 additions & 0 deletions keyword/chapter05/loginPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import useForm from "../../../hooks/useForm.js";
import './loginPage.css';
import {validateLogin} from "../../../utils/validate";

const LoginPage = ()=>{
const login = useForm({
initialValue:{
email: '',
password: '',
},
validate: validateLogin
})
return(
<div className="login_form_container">
<h2>로그인</h2>
<form className="login_form" >
<input className = {`${(login.touched.email && login.errors.email) ? 'error' : 'nonerror'}`}
type={'email'}{...login.getTextInputProps('email')} placeholder="이메일을 입력해주세요!" />
{login.touched.email && login.errors.email && <p style={{color: 'red'}}>{login.errors.email}</p> }
<input className = {`${(login.touched.password && login.errors.password) ? 'error' : ''}`}
type={'password'}{...login.getTextInputProps('password')} placeholder="비밀번호를 입력해주세요!" />
{login.touched.password && login.errors.password && <p style={{color: 'red'}}>{login.errors.password}</p>}
{(login.touched.password && !login.errors.password &&login.touched.email && !login.errors.email)
?<input type={'submit'} value="로그인" className="submit" />
:<input type={'submit'} value="로그인" className="submit gray" disabled/>}

</form>
</div>

)
}

export default LoginPage;
22 changes: 22 additions & 0 deletions keyword/chapter05/myloginPage.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.login_form_container{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
}
.login_form input{
height: 50px;
width: 350px;
border-radius: 8px;
}
.login_form p{
margin-top: 0px ;
font-size: 13px;
}
.submit {
background-color: #ff007c;
color: white;
font-weight: 400;
font-size: 16px
}
40 changes: 40 additions & 0 deletions keyword/chapter05/myloginPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useForm } from "react-hook-form";
import { useState } from "react";
import * as yup from 'yup';
import {yupResolver} from '@hookform/resolvers/yup';
import './loginPage.css';
const LoginPage = ()=>{
const emailSchema = yup.object().shape({
email : yup.string().email('올바른 이메일 형식이 아닙니다 다시 확인해주세요!').required('이메일을 반드시 입력해주세요.'),
})
const pwdSchema = yup.object().shape({
password : yup.string().min(8,'비밀번호는 8자~ 16자 사이로 입력해주세요!',).max(16,'비밀번호는 8자~ 16자 사이로 입력해주세요!').required('비밀번호를 반드시 입력해주세요.'),
})
const emailForm = useForm({
resolver: yupResolver(emailSchema)
})
const pwdForm = useForm({
resolver: yupResolver(pwdSchema)
})

const onSubmit = (data)=>{
console.log('폼 데이터 제출');
console.log(data);
}

return(
<div className="login_form_container">
<h2>로그인</h2>
<form className="login_form" >
<input type={'email'}{...emailForm.register("email")} placeholder="이메일을 입력해주세요!" onFocus={emailForm.handleSubmit(onSubmit)} />
<p style={{color: 'red'}}>{emailForm.formState.errors.email?.message}</p>
<input type={'password'}{...pwdForm.register("password")} placeholder="비밀번호를 입력해주세요!" onFocus={pwdForm.handleSubmit(onSubmit)} />
<p style={{color: 'red'}}>{pwdForm.formState.errors.password?.message}</p>
<input type={'submit'} value="로그인" className="submit" />
</form>
</div>

)
}

export default LoginPage;
25 changes: 25 additions & 0 deletions mission/chapter04/mission01/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 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?
.env
8 changes: 8 additions & 0 deletions mission/chapter04/mission01/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
38 changes: 38 additions & 0 deletions mission/chapter04/mission01/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
13 changes: 13 additions & 0 deletions mission/chapter04/mission01/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<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>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
Loading

0 comments on commit 37de24c

Please sign in to comment.