3. React์˜ Hook

1. React Hook

Hook ๊ฐœ์š”

Hook์€ React ๋ฒ„์ „ 16.8๋ถ€ํ„ฐ React ์š”์†Œ๋กœ ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ Hook์„ ์ด์šฉํ•ด ๊ธฐ์กด Class ๋ฐ”ํƒ•์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ํ•„์š” ์—†์ด ์ƒํƒœ ๊ฐ’๊ณผ ์—ฌ๋Ÿฌ React์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ React๋ฅผ ์“ฐ๋Š” ๋ฐฉ์‹์„ ์™„์ „ํžˆ ๋ฐ”๊พผ ์ปค๋‹ค๋ž€ ๋ณ€ํ™” โ†’ ์˜ˆ์ „์œผ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅ

Hook์˜ ํƒ„์ƒ ๋ฐฐ๊ฒฝ

Hook ์†Œ๊ฐœ

๊ธฐ์กด ๋ฐฉ์‹์— ์žˆ๋˜ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ

1. Wrapper Hell (HoC)

์ปดํฌ๋„ŒํŠธ ์‚ฌ์ด์—์„œ ์ƒํƒœ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ค์šด ๋ฌธ์ œ(render props, ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ) โ†’ ๐Ÿ’ก Hook์€ ๊ณ„์ธต์˜ ๋ณ€ํ™” ์—†์ด ์ƒํƒœ ๊ด€๋ จ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์คŒ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ์ƒํƒœ ๊ด€๋ จ ๋กœ์ง์„ ์ถ”์ƒํ™”ํ•˜๊ณ , ์ด๋ฅผ ์ด์šฉํ•ด ๋…๋ฆฝ์ ์ธ ํ…Œ์ŠคํŠธ์™€ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅ

2. Huge Components, ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šด ๋ณต์žกํ•œ ์ปดํฌ๋„ŒํŠธ

componentDidMount, componentDidUpdate ๋“ฑ ์ƒํƒœ ๊ด€๋ จ ๋กœ์ง, ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ โ†’ ๐Ÿ’ก Hook์„ ํ†ตํ•ด ์„œ๋กœ ๋น„์Šทํ•œ ๊ฒƒ์„ ํ•˜๋Š” ์ž‘์€ ํ•จ์ˆ˜์˜ ๋ฌถ์Œ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‚˜๋ˆ„๋Š” ๋ฐฉ๋ฒ• ์‚ฌ์šฉ

3. Confusing Classes, ์‚ฌ๋žŒ๊ณผ ๊ธฐ๊ณ„๋ฅผ ํ˜ผ๋™์‹œํ‚ค๋Š” Class

React์—์„œ Class๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด JavaScript์˜ this๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์•Œ์•„์•ผ ํ•จ JavaScript์˜ this๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ์–ธ์–ด์—์„œ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜ผ๋ž€ ์œ ๋ฐœ, ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ๊ตฌ์„ฑ์„ ๋งค์šฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ฆ โ†’ ๐Ÿ’ก Hook์€ Class์—†์ด React ๊ธฐ๋Šฅ๋“ค์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ์‹œ

Class Component vs Function Component

์ฐจ์ด์ ClassFunction

์ƒ์„ฑ ๋ฐฉ๋ฒ•

๋ฆฌ์•กํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ extends, ์ƒ์†ํ•ด์„œ ๋งŒ๋“ฆ

ํ•จ์ˆ˜๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒ์„ฑ

์šฉ๋„

์ปดํฌ๋„ŒํŠธ์— state๊ฐ€ ์žˆ๊ณ , ์ƒํƒœ์— ๋”ฐ๋ผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜์•ผ ํ•˜๋ฉด ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ

์ปดํฌ๋„ŒํŠธ์— state๊ฐ€ ์—†๊ณ , ํ•ญ์ƒ ์ •์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ํ‘œ๊ธฐ๋  ์‹œ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ

lifecycle methods

lifecycle methods ์กด์žฌ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ์— ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด ๋†“์œผ๋ฉด ๋ฆฌ์•กํŠธ๊ฐ€ ์•Œ์•„์„œ ๋ถˆ๋Ÿฌ์ฃผ๋Š” ๋ฉ”์†Œ๋“œ

๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์†Œ๋“œ X ํ•จ์ˆ˜๋Š” ํ•œ ๊ฐ€์ง€์˜ ์ผ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋‹จ์œ„

React Hooks

ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ state๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ , ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์†Œ๋“œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ(React 16.8 Ver.)

๊ธฐ์กด

  • ์ƒํƒœ๋ฅผ ๊ฐ€์ง„ ์ปดํฌ๋„ŒํŠธ๋Š” Class Component๋กœ ๋งŒ๋“ค๊ณ , props๋งŒ ์‚ฌ์šฉํ•˜๋Š” ์žฌ์‚ฌ์šฉ์ด ์šฉ์ดํ•œ ์ž‘์€ ์ปดํฌ๋„ŒํŠธ๋Š” Function Component๋กœ ์ž‘์„ฑ

  • Redux์—์„œ๋„ ๋น„์Šทํ•œ ๊ตฌ๋ถ„์ด ์กด์žฌ

ํ˜„์žฌ

  • ๊ทธ๋ƒฅ Function Component๋งŒ ์‚ฌ์šฉ

  • ์ƒํƒœ ๊ด€๋ฆฌ ์œ ๋ฌด๋ฅผ ๋ฐ”๋กœ ์•Œ๊ธฐ ์–ด๋ ค์›€ = ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋จ

  • ๋ณต์žกํ•œ ์š”์†Œ๋Š” ์ „๋ถ€ Hook์œผ๋กœ ๊ฒฉ๋ฆฌ ๋ฐ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ, HoC (Higher-Order Components)

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ(HoC)

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ ธ์™€ ์ƒˆ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” props๋ฅผ UI๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ˜๋ฉด์—, ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€ํ™˜

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ React์˜ ๊ณ ๊ธ‰ ๊ธฐ์ˆ  ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ(HOC)๋Š” React API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ฉฐ, React์˜ ๊ตฌ์„ฑ์  ํŠน์„ฑ์—์„œ ๋‚˜์˜ค๋Š” ํŒจํ„ด

์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ์‹ธ๊ณ  props๋กœ ๋‚ด๋ ค์ฃผ๋Š” ๊ธฐ์ˆ  ๋ถˆํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ณ„์† ์ƒ๊ธฐ๋Š” ๋‹จ์ ์ด ์กด์žฌ

const EnhancedComponent = higherOrderComponent(WrappedComponent);

2. Hooks

Hooks API Reference

๊ธฐ๋ณธ 3๊ฐ€์ง€

  • useState(State Hook) โ‡’ React์˜ State

  • useEffect โ‡’ Side-effect

  • useContext

useState

useState State Hook ์‚ฌ์šฉํ•˜๊ธฐ

useState(State Hook) โ‡’ React์˜ State๋ฅผ ๋‹ค๋ฃธ

// "state"๋ผ๋Š” ์ƒˆ๋กœ์šด ์ƒํƒœ ๊ฐ’์„ ์ •์˜
const [state, setState] = useState(initialState);

์ƒํƒœ๊ฐ’๊ณผ ๊ทธ ๊ฐ’์„ ๊ฐฑ์‹ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ ์ตœ์ดˆ๋กœ ๋ Œ๋”๋ง์„ ํ•˜๋Š” ๋™์•ˆ, ๋ฐ˜ํ™˜๋œ state๋Š” ์ดˆ๊ธฐ๊ฐ’(initialState)๊ณผ ๊ฐ™์Œ

setState(newState);

setState ํ•จ์ˆ˜๋Š” state๋ฅผ ๊ฐฑ์‹ ํ•  ๋•Œ ์‚ฌ์šฉ ์ƒˆ state ๊ฐ’์„ ๋ฐ›์•„ ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง์„ ํ์— ๋“ฑ๋ก useState๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜๋ฐ›์€ ์ฒซ ๋ฒˆ์งธ ๊ฐ’์€ ํ•ญ์ƒ ๊ฐฑ์‹ ๋œ ์ตœ์‹  state

setState((prevState) => prevState + 1);

๊ธฐ์กด ์ƒํƒœ๋ฅผ ์–ป๊ณ ์‹ถ์„ ๋•Œ๋Š” ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์คŒ

useEffect

useEffect Effect Hook ์‚ฌ์šฉํ•˜๊ธฐ useEffect ์™„๋ฒฝ ๊ฐ€์ด๋“œ - by Dan Abramov

useEffect โ‡’ Side-effect๋ฅผ ๋‹ค๋ฃธ

useEffect(didUpdate);

์ผ๋ถ€ component๋Š” ๋ฆฌ์•กํŠธ๊ฐ€ ์•„๋‹Œ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•จ โ†’ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ผ๊ณ  ํ•จ ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด useEffect๋ฅผ ์“ฐ์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Œ

๋ Œ๋”๋ง ์ดํ›„ ํ•ด์•ผ ํ•  ์ผ, ์ฆ‰ React์˜ ์™ธ๋ถ€์™€ ๊ด€๋ จ๋œ ์ผ์„ ์ฒ˜๋ฆฌ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ Œ๋”๋ง ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋ฏ€๋กœ, ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ํ†ตํ•ด ์–ธ์ œ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ• ์ง€ ์ง€์ • ๊ฐ€๋Šฅ(๋ถˆํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ๊ฑด๋„ˆ๋›ฐ๊ธฐ)

ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•จ์œผ๋กœ์จ ์ข…๋ฃŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿค” side effects

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ, ๊ตฌ๋…(subscription) ์„ค์ •ํ•˜๊ธฐ, ์ˆ˜๋™์œผ๋กœ React ์ปดํฌ๋„ŒํŠธ์˜ DOM์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ ๋“ฑ

  1. ์ •๋ฆฌ(clean-up)๋ฅผ ์ด์šฉํ•˜๋Š” Effects โ†’ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ์— ๊ตฌ๋…(subscription)์„ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ์ •๋ฆฌ

  2. ์ •๋ฆฌ(Clean-up)๋ฅผ ์ด์šฉํ•˜์ง€ ์•Š๋Š” Effects โ†’ ์–ด๋–ค ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Œ React๊ฐ€ DOM์„ ์—…๋ฐ์ดํŠธํ•œ ๋’ค ์ถ”๊ฐ€๋กœ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ Ex. ๋„คํŠธ์›Œํฌ ๋ฆฌํ€˜์ŠคํŠธ, DOM ์ˆ˜๋™ ์กฐ์ž‘, ๋กœ๊น… ๋“ฑ์€ ์ •๋ฆฌ(clean-up)๊ฐ€ ํ•„์š” ์—†๋Š” ๊ฒฝ์šฐ

๐Ÿค“ ํŒ

React์˜ class ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์†Œ๋“œ์— ์นœ์ˆ™ํ•˜๋‹ค๋ฉด, useEffect Hook์„ componentDidMount์™€ componentDidUpdate, componentWillUnmount๊ฐ€ ํ•ฉ์ณ์ง„ ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•ด๋„ ์ข‹์Œ

useContext

useContext

context ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„ ๊ทธ context์˜ ํ˜„์žฌ ๊ฐ’์„ ๋ฐ˜ํ™˜, context ๊ฐ’์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒ ๐Ÿ’ก context์˜ ๊ฐ’์— ์ ‘๊ทผํ•  ๋•Œ, Consumer๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋จ useContext๋กœ ์ „๋‹ฌํ•œ ์ธ์ž๋Š” context ๊ฐ์ฒด ๊ทธ ์ž์ฒด์ด์–ด์•ผ ํ•จ

const value = useContext(MyContext);

// ํ‹€๋ฆฐ ์‚ฌ์šฉ: useContext(MyContext.Consumer)
// ํ‹€๋ฆฐ ์‚ฌ์šฉ: useContext(MyContext.Provider)

ํด๋ž˜์Šค์—์„œ์˜ static contextType = MyContext ๋˜๋Š” <MyContext.Consumer>์™€ ๋™์ผ ํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ์—์„œ๋„ context์— ๋„ฃ์–ด ๋‘” ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ฐ€๋Šฅ ํ•œ ํด๋ž˜์Šค์—์„œ ํ•˜๋‚˜์˜ context๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

  • useContext๋ฅผ ํ˜ธ์ถœํ•œ ์ปดํฌ๋„ŒํŠธ๋Š” context ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ญ์ƒ ๋ฆฌ๋ Œ๋”๋ง ๋ฐœ์ƒ

    • ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ ํ™” ๊ฐ€๋Šฅ

  • context์˜ ํ˜„์žฌ ๊ฐ’์€ Hook์„ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด <MyContext.Provider>์˜ value prop์— ์˜ํ•ด ๊ฒฐ์ •

    • <MyContext.Provider>๊ฐ€ ๊ฐฑ์‹ ๋˜๋ฉด Hook์€ provider์—๊ฒŒ ์ „๋‹ฌ๋œ ๊ฐ€์žฅ ์ตœ์‹ ์˜ context value๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ Œ๋”

    • ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ React.memo ๋˜๋Š” shouldComponentUpdate๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ useContext๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ ์ž์ฒด์—์„œ๋ถ€ํ„ฐ ๋‹ค์‹œ ๋ Œ๋”๋ง

โš ๏ธ Context API๋Š” ํ”„๋กญ์Šค ๋“œ๋ฆด๋ง์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ, ์ „์—ญ ์ƒํƒœ๊ด€๋ฆฌ๊ฐ€ ์•„๋‹˜

React์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ธฐ๋ณธ ์›์น™์ธ ๋‹จ๋ฐฉํ–ฅ์„ฑ ๋•Œ๋ฌธ์— Props Drilling(ํ”„๋กญ์Šค ๋“œ๋ฆด๋ง) ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ

  • ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์— ๋™์ผํ•œ ๊ฐ’์„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ฃผ๋Š” api(ํ†ต๋กœ์˜ ๊ฐœ๋…)

  • ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋ ค๋ฉด ์šฉ๋„์— ๋งž๊ฒŒ ๊ตฌ๋ถ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋จ

useRef

useRef

const refContainer = useRef(initialValue);

useRef๋Š” .current ํ”„๋กœํผํ‹ฐ๋กœ ์ „๋‹ฌ๋œ ์ธ์ž(initialValue)๋กœ ์ดˆ๊ธฐํ™”๋œ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ref ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ „ ์ƒ์• ์ฃผ๊ธฐ๋ฅผ ํ†ตํ•ด ์œ ์ง€๋  ๊ฒƒ

ref๋Š” ์ „๋‹ฌ๋˜์ง€ ์•Š์Œ

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋“  props๋ฅผ ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์›์น™์ด์ง€๋งŒ, refs์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Œ ์ด๋Š” React์—์„œ ref๊ฐ€ ์‹ค์ œ prop์ด ์•„๋‹Œ key์ฒ˜๋Ÿผ ํŠน๋ณ„ํ•˜๊ฒŒ ์ทจ๊ธ‰๋˜๊ธฐ ๋•Œ๋ฌธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ HOC์˜ ๊ฒฐ๊ณผ์ธ ์—˜๋ฆฌ๋จผํŠธ์— ref๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ, ref๋Š” ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹Œ ๊ฐ€์žฅ ๋ฐ”๊นฅ์ชฝ ์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ„

useLayoutEffect

useLayoutEffect

  • useLayoutEffect โ†’ useEffect์™€ ์กฐ๊ธˆ ๋‹ค๋ฆ„

  • ์–ด๋Š ํƒ€์ด๋ฐ์— ์ •ํ™•ํ•˜๊ฒŒ ์‹คํ–‰๋˜๋Š”์ง€๋ฅผ ๋ณผ ๋•Œ ์ฐจ์ด๊ฐ€ ์กด์žฌ

useEffect์™€ ๋™์ผํ•˜์ง€๋งŒ, ๋ชจ๋“  DOM ๋ณ€๊ฒฝ ํ›„์— ๋™๊ธฐ์ ์œผ๋กœ ๋ฐœ์ƒ DOM์—์„œ ๋ ˆ์ด์•„์›ƒ์„ ์ฝ๊ณ  ๋™๊ธฐ์ ์œผ๋กœ ๋ฆฌ๋ Œ๋”๋งํ•˜๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•  ๊ฒƒ useLayoutEffect์˜ ๋‚ด๋ถ€์— ์˜ˆ์ •๋œ ๊ฐฑ์‹ ์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๊ธฐ ์ด์ „ ์‹œ์ ์— ๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰

๋จผ์ € useEffect๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๊ณ  ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด useLayoutEffect๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋จ

3. useEffect ํƒ€์ด๋จธ ์˜ˆ์ œ

๐Ÿ”— ์‹ค์Šต ๋งํฌ

React์˜ ์™ธ๋ถ€์— ์šฐ์•„ํ•˜๊ฒŒ ์ ‘๊ทผ ์ด ์ •๋„๋Š” useEffect๋ฅผ ์•ˆ ์“ด๋‹ค๊ณ  ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ์“ฐ๋Š” ์Šต๊ด€์„ ๋“ค์ด๋ฉด ์ข‹์Œ ๋˜๋„๋ก์ด๋ฉด ํ•จ์ˆ˜๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์œผ๋กœ ์˜ฎ๊ธฐ๊ธฐ

useEffect(() => {
    document.title = `Now: ${new Date().getTime()}`;
});

ํƒ€์ด๋จธ๋ฅผ on/offํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ทธ๋ƒฅ ๋งŒ๋“ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ

// TimerControl.tsx

function Timer() {
  useEffect(() => {
    setInterval(() => {
        document.title = `Now: ${new Date().getTime()}`;
    }, 100);
  });

  return (
      <p>Playing</p>
  );
}

export default function TimerControl() {
  const [playing, setPlaying] = useState(false);

  const handleClick = () => {
    setPlaying(!playing);
  };

  return (
      <div>
        {playing ? (
            <Timer />
        ) : (
            <p>Stop</p>
        )}
        <button type="button" onClick={handleClick}>Toggle</button>
      </div>
  );
}
  • ํ† ๊ธ€์„ ๋ˆŒ๋Ÿฌ setInterval์„ ๋„๋ ค๊ณ  ํ•ด๋„ ๊ณ„์† ์‹คํ–‰๋˜๋Š” ์˜ค๋ฅ˜

์ข…๋ฃŒ ์ฒ˜๋ฆฌ

ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•ด์„œ clean-up

// TimerControl.tsx

useEffect(() => {
    const savedTitle = document.title;
    
    const id = setInterval(() => {
        document.title = `Now: ${new Date().getTime()}`;
        }, 100);
    
    return () => {
        document.title = savedTitle;
        clearInterval(id);
    };
});

์˜์กด์„ฑ ๋ฐฐ์—ด

์˜์กด์„ฑ ๋ฐฐ์—ด์—์„œ ์•„๋ฌด ๊ฒƒ๋„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋งจ ์ฒ˜์Œ์— ๋”ฑ ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰ ์ฃผ๋กœ API๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์„ ๋•Œ ์‚ฌ์šฉ ๋นˆ ๋ฐฐ์—ด([])์„ ์ „๋‹ฌํ•œ๋‹ค๋ฉด effect ์•ˆ์— ์žˆ๋Š” props์™€ state๋Š” ํ•ญ์ƒ ์ดˆ๊ธฐ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋  ๊ฒƒ

export default function TimerControl() {
    const [count, setCount] = useState(0);
    
    useEffect(() => {
        console.log('effect');
        }, []);

  return (
        <div>
          <button type='button' onClick={() => setCount(count + 1)}>Increase</button>
        </div>
    )
}

๐Ÿšจ onClick={() => setCount(count + 1)}์„ onClick={setCount(count + 1)}๋กœ ์ž˜๋ชป ์“ด๋‹ค๋ฉด ๋ฌดํ•œ ๋ฆฌ๋ Œ๋”๋ง ๋ฐœ์ƒ

์ฒ˜์Œ์— ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๊ธฐ

์˜์กด์„ฑ ๋ฐฐ์—ด์ด ์—†์„ ๊ฒฝ์šฐ ๋ฌดํ•œ ๋ฆฌ๋ Œ๋”๋ง

products๋ฅผ ์–ป๋Š” ๊ณณ์—์„œ ์‚ฌ์šฉ(๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋งจ ์ฒ˜์Œ)

// App.tsx

const [products, setProducts] = useState<Product[]>([]);

useEffect(() => {
    const fetchProducts = async () => {
        const url = 'http://localhost:3000/products';
        const response = await fetch(url);
        const data = await response.json();
        setProducts(data.products);
    };
    fetchProducts();
}, []);

์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์ด์šฉํ•ด Fetchํ•  ๋•Œ ์ฃผ์˜์‚ฌํ•ญ

Fetching data

useEffect(() => {
  let ignore = false;

  async function startFetching() {
    const json = await fetchTodos(userId);
    if (!ignore) {
      setTodos(json);
    }
  }

  startFetching();

  return () => {
    ignore = true;
  };
}, [userId]);

4. React StrictMode

React StrictMode

StrictMode๋Š” ์ž์†๋“ค์— ๋Œ€ํ•œ ๋ถ€๊ฐ€์ ์ธ ๊ฒ€์‚ฌ์™€ ๊ฒฝ๊ณ ๋ฅผ ํ™œ์„ฑํ™” ๊ฐœ๋ฐœ ๋ชจ๋“œ์—์„œ๋งŒ ํ™œ์„ฑํ™”๋˜๊ธฐ ๋•Œ๋ฌธ์—, ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ์—๋Š” ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š์Œ

  • ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋ฐœ๊ฒฌ

  • ๋ ˆ๊ฑฐ์‹œ ๋ฌธ์ž์—ด ref ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๊ฒฝ๊ณ 

  • ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š” findDOMNode ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๊ฒฝ๊ณ 

  • ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ถ€์ž‘์šฉ ๊ฒ€์‚ฌ

  • ๋ ˆ๊ฑฐ์‹œ context API ๊ฒ€์‚ฌ

  • Ensuring reusable state

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

root.render((
    <React.StrictMode>
        <App/>
    </React.StrictMode>
));
  • <App /> ์ปดํฌ๋„ŒํŠธ ๊ฐ๊ฐ์˜ ์ž์†๊นŒ์ง€ ๊ฒ€์‚ฌ๊ฐ€ ์ด๋ฃจ์–ด์ง

์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ถ€์ž‘์šฉ ๊ฒ€์‚ฌ

โš ๏ธ useEffect ๋“ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ ๋‘ ๋ฒˆ ์‹คํ–‰๋˜๋Š” ๋ฌธ์ œ(์ฝ˜์†”์— ๋‘ ๋ฒˆ์”ฉ ํ˜ธ์ถœ ์ถœ๋ ฅ)

์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ถ€์ž‘์šฉ ๊ฒ€์‚ฌ <React.StrictMode>๋กœ ์ปดํฌ๋„ŒํŠธ ์ „์ฒด๋ฅผ ๊ฐ์Œ€ ๊ฒฝ์šฐ, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ์ฐพ์œผ๋ ค๊ณ  Effect ๋“ฑ์„ ๋‘ ๋ฒˆ์”ฉ ์‹คํ–‰ ๋‘ ๋ฒˆ ์ฒดํฌํ•ด์„œ ๋‘ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฅผ ๊ฒฝ์šฐ ํ•จ์ˆ˜์˜ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ํฌ๋‹ค๊ณ  ๊ฒฝ๊ณ  ํ‰์†Œ์—๋Š” ํฐ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, API ๋“ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด์ƒํ•˜๋‹ค๊ณ  ๋Š๋‚„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ 

Last updated