-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
π [#3] React Hooks μν°ν΄μ μΆκ°νλ€
- Loading branch information
1 parent
8a6a4ca
commit dd99cfa
Showing
7 changed files
with
397 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,280 @@ | ||
--- | ||
title: React Hooks κΈ°μ΄ | ||
description: Reactμ Hooksμ 무μμ΄κ³ , λνμ μΈ Hooksλ₯Ό μμ보μ | ||
createdAt: 2022-06-10 | ||
category: React | ||
tags: | ||
- React | ||
- TypeScript | ||
--- | ||
|
||
## π React.js Hooks | ||
|
||
**Hooks**λ Componentμμ λ°μ΄ν°λ₯Ό κ΄λ¦¬νκ±°λ λ°μ΄ν°κ° λ³κ²½λ λ μνΈμμ©νκΈ° μν΄ μ¬μ©λλ κ²μ΄λ€. κΈ°μ‘΄μ React.jsμμλ Component λ΄λΆμ Stateμ μλͺ μ£ΌκΈ°λ₯Ό κ΄λ¦¬νλ €λ©΄ Class Componentλ₯Ό μ¬μ©ν΄μΌ νμΌλ, Function Componentμμ μ΄λ¬ν κΈ°λ₯μ ꡬννκΈ° μν΄ 16.8 λ²μ μ΄νλ‘ μΆκ°λ μλ‘μ΄ κΈ°λ₯μ΄λ€. | ||
|
||
μ¦, Function Componentμμ React stateμ μλͺ μ£ΌκΈ° κΈ°λ₯(lifecycle features)μΒ **μ°λ(hook into)**Β ν μ μκ² ν΄μ£Όλ κ²μ΄ λ°λ‘ Hookμ΄λ€. | ||
|
||
### Hooksλ₯Ό νμ©νλ μ΄μ | ||
|
||
**κΈ°μ‘΄ React.js λ¬Έμ μ ** | ||
|
||
- Component μ¬μ΄μμ Stateμ κ΄λ ¨λ λ‘μ§μ μ¬μ¬μ©νκΈ° μ΄λ ΅λ€. | ||
- 볡μ‘ν Componentλ€μ μ΄ν΄νκΈ° μ΄λ ΅λ€. | ||
- Class Componentμ `this`μ λ¬Έμ μ | ||
|
||
**Hooksμ μ₯μ ** | ||
|
||
- Componentμ ν¨μκ° λ§μμ§ λλΆν° Class Componentλ‘ λ¦¬ν©ν λ§ν νμκ° μλ€. | ||
- UIμ λ‘μ§μ μλΉκ² λΆλ¦¬ν΄ λ κ°μ§ λͺ¨λ μ¬μ¬μ©ν μ μλ€. | ||
- κΈ°μ‘΄ μ½λλ₯Ό λ€μ μμ±ν νμ μμ΄ μΌλΆ Component λ΄λΆμμ Hookμ μ¬μ©ν μ μλ€. | ||
- Hookμ μ¬μ©νλ©΄ Componentλ‘λΆν° μν κ΄λ ¨ λ‘μ§μ μΆμνν μ μλ€. μ¦, Componentλ³λ‘ λ 립μ μΈ ν μ€νΈμ μ¬μ¬μ©μ΄ κ°λ₯νκ³ , Component κ° κ³μΈ΅ λ³ν μμ΄ μν κ΄λ ¨ λ‘μ§μ μ¬μ¬μ©ν μ μλ€. | ||
|
||
### Hooks μ¬μ© κ·μΉ | ||
|
||
- Hooksλ λ°λμ React.js ν¨μ(Component, Hook) λ΄μμλ§ μ¬μ©ν μ μλ€. | ||
- Hooksμ μ΄λ¦μ `use`λ‘ λ°λμ μμνλ€. | ||
- μ΅μμ λ 벨μμλ§ Hooksλ₯Ό νΈμΆν μ μλ€.(ex. `if`, `for`, μ½λ°± ν¨μ, μ€μ²©λ ν¨μ λ΄μμλ λΆκ°λ₯) | ||
μ¦, Component λ΄λΆμ 첫 λ²μ§Έ μ€κ΄νΈ(`{}`) λ΄μ μμ±ν΄μΌ νλ€. | ||
|
||
### State Hook | ||
|
||
κ°λ¨ν μν κ΄λ¦¬μ‘°μ°¨λ Class Componentλ‘ μμ±ν΄μΌ νλλ°, μ΄λ Function Componentλ³΄λ€ λ³΅μ‘νκ³ μλ¬κ° λ°μνκΈ° μ¬μ°λ©° μ μ§ λ³΄μκ° νλ€λ€. λ°λΌμ State Hookμ νμ©ν΄ Function Componentμμ κ°λ¨ν μ¬μ©ν μ μλ€. | ||
|
||
```jsx | ||
const App = () => { | ||
const [state, setState] = useState('μ΄κΈ°κ°'); | ||
}; | ||
``` | ||
|
||
Function Component λ΄λΆμ λμ μΈ λ°μ΄ν°λ₯Ό κ΄λ¦¬ν μ μκ² ν΄μ£Όλ Hook. | ||
|
||
- μνλ₯Ό κ΄λ¦¬νκΈ° μν μ½λ μμ λ§€μ° κ°λ¨ν΄μ§λ μ₯μ μ΄ μλ€. | ||
- μ΄λ κ² State HookμΌλ‘ μ€μ λ `state` κ°μ μ½κΈ° μ μ©μ΄λ―λ‘ μμ νλ©΄ μλλ€. | ||
- `state` κ°μ λ³κ²½νκΈ° μν΄μλ `setState` ν¨μλ₯Ό μ¬μ©ν΄μΌ νλ€. | ||
- `state` κ°μ΄ λ³κ²½λλ κ²½μ° μλμΌλ‘ Componentκ° λ€μ λ λλ§ λλ€. | ||
- `setState` ν¨μ νμ©λ² | ||
- μ§μ λ³κ²½ν `state` κ°μ μΈμλ‘ μ λ ₯νλ λ°©μ. | ||
```jsx | ||
setState('λ³κ²½ν κ°'); | ||
``` | ||
- νμ¬ `state` κ°μ 맀κ°λ³μλ‘ λ°λ ν¨μλ₯Ό μ λ¬νλ λ°©μ. π | ||
```jsx | ||
setState((current) => { | ||
return current + 1; | ||
}); | ||
``` | ||
|
||
### Effect Hook | ||
|
||
- ~~Component Life Cycle~~ | ||
 | ||
|
||
React Component μμμ λ°μ΄ν°λ₯Ό κ°μ Έμ€κ±°λ ꡬλ νκ³ , DOMμ μ§μ μ‘°μνλ λ±μ λ€μν μμ λ€μ Side Effects λλ Effects λΌκ³ νλ€. | ||
|
||
Side Effectsμλ Clean-upμ΄ νμνμ§ μμ κ²μ΄ μλλ°, μ¦, DOMμ μ λ°μ΄νΈ ν λ€ μΆκ°λ‘ μ½λλ₯Ό μ€νν΄μΌ νλ κ²½μ°μλ Clean-upμ΄ νμνμ§ μλ€. ν΄λΉ Componentλ λ λλ§ μ΄ν κ³μ μ¬μ©λκΈ° λλ¬Έμ΄λ€. | ||
|
||
μ΄μ λ¬λ¦¬ Clean-upμ΄ νμν Side Effectsλ μλ€. μλ₯Ό λ€μ΄ λ©λͺ¨λ¦¬λ₯Ό λ§μ΄ μ¬μ©νλ Componentμ κ²½μ°μλ λ©λͺ¨λ¦¬ λμλ₯Ό λ§κΈ° μν΄ μ¬μ©νμ§ μλ κ²½μ° λ©λͺ¨λ¦¬λ₯Ό ν΄μ ν΄μ£Όμ΄μΌ νλ€. μ¦, DOM λ λλ§ μ΄ν μΆκ°λ‘ νμνμ§ μμ μ½λμ΄κ±°λ, λ©λͺ¨λ¦¬λ₯Ό λ§μ΄ μ¬μ©νλ λ±μ κ²½μ°μλ Clean-upμ ν΄μ£Όμ΄μΌ νλ€. | ||
|
||
μ΄λ¬ν λΆλΆμ ν΄κ²°νκΈ° μν΄ Class Componentμμλ `componentWillUnmount()`λ±μ μλͺ μ£ΌκΈ° λ©μλλ₯Ό νμ©νμ§λ§, Function Componentμμλ Effect Hookμ μ¬μ©νλ€. | ||
|
||
μ¦, Function Component μΈλΆμμ λ‘컬μ μν κ°μ λ³κ²½νλ κ²μ μλ―Ένλ€. λ€λ§, μ΄λ¬ν κ³Όμ μ λ€λ₯Έ Componentμ μν₯μ μ€ μλ μμ΄ λ λλ§ κ³Όμ μμλ ꡬνν μκ° μλ€. | ||
|
||
λ°λΌμ Effect Hookμ νμ©ν΄ Function Component λ΄μμ side effectsλ₯Ό μνν μ μκ² ν΄μ€λ€. | ||
|
||
νμμ μΈ APIλ₯Ό λΆλ¬μ€κ±°λ λ°μ΄ν°λ₯Ό κ°μ Έμ¬ λ **`useEffect()`**λ₯Ό μ¬μ©νλ©΄ λͺ¨λ λ λλ§νλ μμλ§λ€ μνλ μμ μ μνν μ μμ΄ μ½λλ₯Ό μ€λ³΅ν νμκ° μλ€. | ||
|
||
```jsx | ||
const App = () => { | ||
useEffect(effectCallback, Deps?); | ||
// effectCallback: μ§μ λ λμ λ³μκ° λ³κ²½λλ κ²½μ° μ€νν ν¨μ | ||
// Deps: λ³κ²½μ κ°μ§ν λμ λ³μλ€μ λ°°μ΄ | ||
} | ||
``` | ||
Function Component λ΄λΆμμ Side Effectλ₯Ό μννλ Hook. | ||
- Componentκ° μ΅μ΄λ‘ λ λλ§λ λ, μ§μ ν Stateλ Propsκ° λ³κ²½λ λ λ± λ€μν κ²½μ°μ `effectCallback` ν¨μκ° νΈμΆλλ€. | ||
- Depsκ° λΉ λ°°μ΄`[]`μ΄λΌλ©΄, Component μ΅μ΄ μμ± μ νλ²λ§ μ€ννλ ν¨κ³Όλ₯Ό μ§μ νλ κ²μ΄λ€. | ||
- useEffect Hook λ΄μμ λ€λ₯Έ ν¨μλ₯Ό λ°ννλ κ²μ `state` κ°μ΄ λ³κ²½λμ΄ Componentκ° λ€μ λ λλ§λκΈ° μ κ³Ό Componentκ° μμ΄μ§ λ νΈμΆν ν¨μλ₯Ό λ°ννλ κ²μ΄λ€. | ||
```jsx | ||
const App = () => { | ||
useEffect(() => { | ||
// ... Stateκ° λ³κ²½λ λ, Componentλ₯Ό λ λλ§ν λ | ||
} | ||
|
||
return () => { | ||
// ... Componentλ₯Ό λ€μ λ λλ§ν λ, Componentκ° μμ΄μ§ λ | ||
} | ||
); | ||
} | ||
``` | ||
### Memo Hook | ||
```jsx | ||
const App = () => { | ||
const [firstName, setFirstName] = useState('μ² μ'); | ||
const [lastName, setLastName] = useState('κΉ'); | ||
|
||
const fullName = useMemo(() => { | ||
return `${lastName}${firstName}`; | ||
}, [firstName, lastName]); | ||
}; | ||
``` | ||
μ§μ ν Stateλ Propsκ° λ³κ²½λ κ²½μ° ν΄λΉ κ°μ νμ©ν΄ κ³μ°λ κ°μ λ©λͺ¨μ΄μ μ΄μ νμ¬ λ€μ λ λλ§ν λ λΆνμν μ°μ°μ μ€μ¬μ€ λ νμ©νλ€. | ||
- Memo Hook μ°μ°μ λ λλ§ λ¨κ³μμ μ΄λ£¨μ΄μ§λ€. λ°λΌμ μ€λ 걸리λ λ‘μ§μ μμ±νμ§ μλλ‘ κΆμ₯λλ€. μ±λ₯ νλ½ μ΄μκ° λ°μν μ μλ€. | ||
```jsx | ||
import React, { useState, useMemo } from 'react'; | ||
|
||
function App() { | ||
const [foo, setFoo] = useState(0); | ||
const [bar, setBar] = useState(0); | ||
|
||
let multi = useMemo(() => { | ||
return foo * bar; | ||
}, [foo, bar]); | ||
|
||
return ( | ||
<div className='App'> | ||
<input | ||
type='number' | ||
value={foo} | ||
onChange={(e) => setFoo(+e.target.value)} | ||
/> | ||
<input | ||
type='number' | ||
value={bar} | ||
onChange={(e) => setBar(+e.target.value)} | ||
/> | ||
<div>{multi}</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default App; | ||
``` | ||
### Callback Hook | ||
```jsx | ||
const App = () => { | ||
const [firstName, setFirstName] = useState('μ² μ'); | ||
const [lastName, setLastName] = useState('κΉ'); | ||
|
||
const getFullName = useCallback(() => { | ||
return `${lastName}${firstName}`; | ||
}, [firstName, lastName]); | ||
|
||
return <>{getFullName()}</>; | ||
}; | ||
``` | ||
Callback Hookμ ν¨μλ₯Ό λ©λͺ¨μ΄μ μ΄μ νκΈ° μν΄ μ¬μ©νλ Hook. | ||
- Componentκ° λ€μ λ λλ§λ λ λΆνμνκ² ν¨μκ° μ¬μμ±λλ κ²μ λ°©μ§ν μ μλ€. | ||
- Memo Hookμ΄ λ³μλ₯Ό λ©λͺ¨μ΄μ μ΄μ νλ€λ©΄, Callback Hookμ ν¨μλ₯Ό λ©λͺ¨μ΄μ μ΄μ νλ€. | ||
`useMemo(() β fn, deps)`μ `useCallback(fn, deps)`λ λμΌνλ€. | ||
```jsx | ||
import React, { useState, useCallback } from 'react'; | ||
|
||
function App() { | ||
const [foo, setFoo] = useState(0); | ||
const [bar, setBar] = useState(0); | ||
|
||
let calc = useCallback(() => { | ||
return foo + bar; | ||
}, [foo, bar]); | ||
|
||
return ( | ||
<div className='App'> | ||
<input | ||
type='number' | ||
value={foo} | ||
onChange={(e) => setFoo(+e.target.value)} | ||
/> | ||
<input | ||
type='number' | ||
value={bar} | ||
onChange={(e) => setBar(+e.target.value)} | ||
/> | ||
<div>{calc()}</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default App; | ||
``` | ||
### Reference Hook | ||
```jsx | ||
const App = () => { | ||
const inputRef = useRef(null); | ||
const handleClickBtn = () => { | ||
inputRef.current.focus(); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<input ref={inputRef} type='text' /> | ||
<button onClick={handleClickBtn}>inputμΌλ‘ ν¬μ»€μ€νκΈ°</button> | ||
</div> | ||
); | ||
}; | ||
``` | ||
Component μμ μ£ΌκΈ° λ΄μμ μ μ§ν ref κ°μ²΄λ₯Ό λ°ννλ Hook. | ||
κΈ°λ³Έμ μΌλ‘ Stateκ° λ³κ²½λλ©΄ λ€μ λ λλ§λλ€. λ€λ§, κ°μ λ³κ²½νλλΌλ λ€μ λ λλ§λμ§ μκ²λ ν΄μΌ ν μν©μ΄ μμ μ μλ€. μ΄λ `let`μ νμ©ν΄ λ³μλ₯Ό μ μΈνλ€λ©΄ Componentλ₯Ό λ€μ λ λλ§ν λ `let` μ μΈλ¬Έμ΄ λ€μ μ μΈλμ΄ κ°μ΄ μ΄κΈ°νλκ² λλ€. | ||
λ°λΌμ μ΄λ° μν©μμ Reference Hookμ νμ©νλ€. | ||
- `ref` κ°μ²΄λ `current` μμ±μ κ°μ§λ©° μ΄λ₯Ό μμ λ‘κ² λ³κ²½ν μ μλ€. | ||
- useRefμ μν΄ λ°νλ ref κ°μ²΄κ° λ³κ²½λλλΌλ Componentκ° λ€μ λ λλ§λμ§ μλλ€. | ||
- μΌλ°μ μΌλ‘ DOM μμμ μ κ·Όν λ ν΄λΉ μμμ `ref` μμ±μ μΆκ°νμ¬ μ¬μ©νλ€. | ||
μ¦, λ€μκ³Ό κ°μ΄ μμ±νλ©΄ `inputRef.current`μ ν΄λΉ `input` μμκ° ν λΉλλ€. | ||
```jsx | ||
<input ref={inputRef} type='text' /> | ||
``` | ||
```jsx | ||
import React, { useRef } from 'react'; | ||
|
||
function App() { | ||
const inputRef = useRef(null); | ||
return ( | ||
<div className='App'> | ||
<input ref={inputRef} /> | ||
<button | ||
onClick={() => { | ||
alert(inputRef.current.value); | ||
}} | ||
> | ||
ν΄λ¦νκΈ° | ||
</button> | ||
</div> | ||
); | ||
} | ||
|
||
export default App; | ||
``` | ||
### Custom Hook | ||
μμ λ§μ Hookμ λ§λ€μ΄ Component λ‘μ§μ μ¬μ¬μ©ν μ μλ€. μ¦, UI μμμ μ¬μ¬μ©μ±μ λμ΄κΈ° μν΄ Componentλ₯Ό νμ©νκ³ , λ‘μ§μ μ¬μ¬μ©μ±μ λμ΄κΈ° μν΄ Custom Hookμ νμ©νλ€. | ||
```jsx | ||
fucntion useCustomHook(args) { | ||
const [status, setStatus] = useState(null); | ||
// ... | ||
return status; | ||
} | ||
``` | ||
- νλμ λ‘μ§μ΄ μ¬λ¬ λ² νμ©λλ κ²½μ° ν¨μλ₯Ό λΆλ¦¬νλ κ²μ²λΌ HookμΌλ‘ λΆλ¦¬νλ κ²μ΄λ€. | ||
- useλ‘ μμν΄μΌ νλ€. | ||
- νλμ Hook λ΄μ `state`λ 곡μ λμ§ μλλ€. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { allArticles } from '@contentlayer'; | ||
import { useMDXComponent } from 'next-contentlayer/hooks'; | ||
import { notFound } from 'next/navigation'; | ||
import Image from 'next/image'; | ||
|
||
interface IArticlePageProps { | ||
params: { slug: string }; | ||
} | ||
|
||
const ArticlePage = ({ params: { slug } }: IArticlePageProps) => { | ||
const article = allArticles.find((article) => article.slugAsParams === slug); | ||
|
||
if (!article) notFound(); | ||
|
||
const MDXContent = useMDXComponent(article.body.code); | ||
|
||
return ( | ||
<section className='flex flex-col px-4 py-10 items-center'> | ||
<> | ||
{article.thumbnail ? ( | ||
<Image | ||
src={article.thumbnail} | ||
alt={article.title} | ||
width={400} | ||
height={300} | ||
/> | ||
) : ( | ||
<div>{article.title}</div> | ||
)} | ||
</> | ||
<h1 className='text-display2 font-extrabold'>{article.title}</h1> | ||
<p>{article.description}</p> | ||
<p>{new Date(article.createdAt).toLocaleDateString()}</p> | ||
<p>{article.category}</p> | ||
|
||
<ul> | ||
{article.tags.map((tag) => ( | ||
<span key={tag}>{tag}</span> | ||
))} | ||
</ul> | ||
<div className='w-full h-0.5 bg-primary-500 my-4' /> | ||
<article className='prose prose-primary max-w-3xl'> | ||
<MDXContent /> | ||
</article> | ||
</section> | ||
); | ||
}; | ||
|
||
export default ArticlePage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Card from '@/src/components/ui/Card'; | ||
import { allArticles } from '@contentlayer'; | ||
|
||
const ArticlesPage = () => { | ||
return ( | ||
<section className='flex flex-col items-center justify-between px-4 py-10 tablet:py-40'> | ||
<section className='flex flex-wrap gap-8'> | ||
{allArticles.map((article) => ( | ||
<Card | ||
key={article._id} | ||
articlePreview={{ | ||
category: article.category, | ||
title: article.title, | ||
description: article.description, | ||
createdAt: new Date(article.createdAt).toLocaleDateString(), | ||
tags: article.tags, | ||
slug: article.slug, | ||
thumbnail: { | ||
src: article.thumbnail, | ||
alt: article.title, | ||
}, | ||
}} | ||
/> | ||
))} | ||
</section> | ||
</section> | ||
); | ||
}; | ||
|
||
export default ArticlesPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.