wam
w__am ๊ฐœ๋ฐœ๋…ธํŠธ
wam
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (165)
    • CS ์ง€์‹ (10)
      • ์ž๋ฃŒ๊ตฌ์กฐ (0)
      • ์•Œ๊ณ ๋ฆฌ์ฆ˜ (0)
      • ์ปดํ“จํ„ฐ ๊ตฌ์กฐ (0)
      • ์šด์˜์ฒด์ œ (0)
      • ๋„คํŠธ์›Œํฌ (7)
      • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (0)
      • ๋””์ž์ธ ํŒจํ„ด (3)
    • Frontend (131)
      • Three.js (64)
      • NPM (1)
      • Nest.js (19)
      • React (10)
      • Apollo (7)
      • TypeScript (2)
      • JavaScript (12)
      • HTML, CSS (1)
      • Jest (3)
      • E2E (5)
      • Cypress (7)
    • Database (12)
      • TypeORM (12)
    • IT ์ง€์‹ (8)
      • ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค (3)
      • ๋„คํŠธ์›Œํฌ (1)
      • ๋ฐ์ดํ„ฐ ํฌ๋งท (2)
      • ๊ธฐํƒ€ (2)
    • IT Book (2)
    • ์œ ์šฉํ•œ ์‚ฌ์ดํŠธ (1)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ํƒœ๊ทธ
  • ๋ฐฉ๋ช…๋ก
  • ๐Ÿฑ Github

์ธ๊ธฐ ๊ธ€

ํƒœ๊ทธ

  • ๋ฐ์ดํ„ฐ ํฌ๋งท
  • mapped types
  • ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ตœ์ ํ™”
  • joi ์—๋Ÿฌ
  • Interface
  • API
  • Decorators
  • reactive variables
  • ๋””์ž์ธ ํŒจํ„ด
  • ํ•จ์ˆ˜ ๋ฆฌํ„ฐ๋Ÿด
  • isabstract
  • ์‚ผ๊ฐํ•จ์ˆ˜
  • e.preventdefault()
  • type-graphql
  • math.cos()
  • ํ•จ์ˆ˜ ์„ ์–ธ๋ฌธ
  • react ์„ฑ๋Šฅ ์ตœ์ ํ™”
  • threejs ๊ฐœ๋ฐœ ํ•  ๋•Œ ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ
  • ํ•จ์ˆ˜์˜ ๋ฒ”์œ„
  • ์˜คํ”„-ํ”„๋ ˆ๋ฏธ์Šค(off-premise) ๋ฐฉ์‹
  • ์Šค์ฝ”ํ”„
  • ์›ํ˜•์ ์ธ ์›€์ง์ž„
  • ํ•จ์ˆ˜ ํ‘œํ˜„์‹
  • math.sin()
  • getdelta()
  • gridhelper
  • ์ดˆ๊ธฐ ํ™˜๊ฒฝ์„ค์ •
  • axeshelper
  • three.js ๊ตฌ์„ฑ ์š”์†Œ
  • getelapsedtime()

์ตœ๊ทผ ๊ธ€

๊ด€๋ฆฌ์ž

๊ธ€์“ฐ๊ธฐ / ์Šคํ‚จํŽธ์ง‘ / ๊ด€๋ฆฌ์žํŽ˜์ด์ง€
hELLO ยท Designed By ์ •์ƒ์šฐ.
wam

w__am ๊ฐœ๋ฐœ๋…ธํŠธ

Hook์˜ ๊ทœ์น™
Frontend/React

Hook์˜ ๊ทœ์น™

2024. 5. 8. 04:04
๐Ÿง React Hooks๋ž€?
ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ state ๊ด€๋ฆฌ์™€ Life Cycle์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ธฐ์ˆ ์ด๋‹ค.


๐ŸงHooks์˜ ๋„์ž… ์ด์œ ?
ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ช‡๋ช‡ ๋ถˆํŽธํ•œ ์ ๋“ค์„ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด

- this ๊ฐ’์˜ ๋ณ€๊ฒฝ
- ๋–จ์–ด์ง€๋Š” ๊ฐ€๋…์„ฑ
- HOCํŒจํ„ด์˜ Wrapper ์ง€์˜ฅ


๐ŸงHook์˜ ๊ทœ์น™
์ตœ์ƒ์œ„(at the Top Level)์—์„œ๋งŒ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
- ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ ๋˜๋Š” ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
- ๋ชจ๋“  ๋ Œ๋”๋ง์—์„œ ๋™์ผํ•œ ์ˆœ์„œ๋กœ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

์˜ค์ง React ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
- ์ผ๋ฐ˜์ ์ธ JavaScript ํ•จ์ˆ˜์—์„œ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
- React ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

 

 

Hook ์ด๋ž€?

  • 2018๋…„ React Conferences์—์„œ ์ฒ˜์Œ ์†Œ๊ฐœ๋˜์–ด React v16.8์— ๋„์ž…๋œ ๊ธฐ์ˆ 
  • ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ React ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” JavaScript ํ•จ์ˆ˜
  • ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•  ํ•„์š” ์—†์ด ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ state ๊ด€๋ฆฌ์™€ Life Cycle์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ์ˆ 
  • Hook์˜ ์ข…๋ฅ˜
    • useState()
    • useEffect()
    • useMemo()
    • useRef()
    • useCallback()
    • …

 

 

Hook์˜ ๊ทœ์น™

 

์ตœ์ƒ์œ„(at the Top Level)์—์„œ๋งŒ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

  • ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ ๋˜๋Š” ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
    • Hook ํ˜ธ์ถœ ์ˆœ์„œ๊ฐ€ ์ปดํฌ๋„ŒํŠธ์˜ ๋ Œ๋”๋ง ์ˆœ์„œ์™€ ์ผ์น˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.
    • ๋”ฐ๋ผ์„œ ๋ชจ๋“  ๋ Œ๋”๋ง์—์„œ ๋™์ผํ•œ ์ˆœ์„œ๋กœ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.


    ๋งŒ์•ฝ ์กฐ๊ฑด๋ฌธ์ด๋‚˜ ๋ฐ˜๋ณต๋ฌธ์•ˆ์—์„œ ํ›…์„ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด Hook์ด ์–ด๋–ค ์กฐ๊ฑด์— ๋”ฐ๋ผ ์‹คํ–‰๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.
    • ๋ Œ๋”๋ง ๋•Œ๋งˆ๋‹ค ๋งจ ์ฒ˜์Œ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๋ฆฌ์•กํŠธ๊ฐ€ ๊ธฐ์–ตํ•ด ๋†“์€ Hook์˜ ํ˜ธ์ถœ ์ˆœ์„œ๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ์‹คํ–‰๋  ๊ฒƒ์ด๊ณ  ๊ฒฐ๊ตญ ๋ฒ„๊ทธ๋ฅผ ์ดˆ๋ž˜ํ•œ๋‹ค.
    • ์ด๋Š” ํ•ญ์ƒ ๋ฆฌ์•กํŠธ ํ•จ์ˆ˜ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ๋งŒ ํ›…์„ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š” ์ด์œ ์ด๋‹ค.
    • ๋ฆฌ์•กํŠธ๋Š” ์ด Hook๋“ค์„ ํ˜ธ์ถœ๋˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ์ €์žฅํ•ด ๋†“๋Š”๋‹ค.(=LinkedList)
    • ๊ทธ๋ž˜์„œ ๋งค ๋ Œ๋”๋ง๋งˆ๋‹ค ์ˆœ์„œ๋Œ€๋กœ ํ›…์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

 

 

์˜ค์ง React ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

  • ์ผ๋ฐ˜์ ์ธ JavaScript ํ•จ์ˆ˜์—์„œ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
  • React ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
  • ์ปค์Šคํ…€ Hook์€ 'use'๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค.

 

 

์ž˜๋ชป๋œ ์˜ˆ

๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ ๋˜๋Š” ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.

import React, { useState, useEffect } from 'react';

function BadCounter() {
  const [count, setCount] = useState(0);

  // ์กฐ๊ฑด๋ฌธ ์•ˆ์—์„œ useEffect๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋‚˜์œ ์˜ˆ์‹œ
  if (count === 5) {
    useEffect(() => {
      alert('Count reached 5!');
    }, []);
  }

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

export default BadCounter;

  • if ๋ฌธ ๋‚ด์—์„œ ์กฐ๊ฑด์— ๋”ฐ๋ผ useEffect๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ๋‹ค. React Hook ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค.
  • useEffect๋Š” ํ•ญ์ƒ ์ปดํฌ๋„ŒํŠธ์˜ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๊ณ , ์กฐ๊ฑด๋ฌธ ์•ˆ์—์„œ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
  • ์ด๋Ÿฌํ•œ ์ฝ”๋“œ๋Š” ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋™์ž‘์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๊ณ , React์˜ ์ตœ์ ํ™”๋ฅผ ๋ฐฉํ•ดํ•œ๋‹ค.
  • count === 5๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ useEfffect์„ ๊ฑด๋„ˆ๋›ฐ๊ฒŒ ๋˜๋ฉด์„œ Hook์˜ ํ˜ธ์ถœ ์ˆœ์„œ๊ฐ€ ๋‹ฌ๋ผ์ง€๊ฒŒ ๋œ๋‹ค.

 

 

์˜ณ์€ ์˜ˆ

import React, { useState, useEffect } from 'react';

function GoodCounter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // count๊ฐ€ 5๊ฐ€ ๋˜๋ฉด alert์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
    if (count === 5) {
      alert('Count reached 5!');
    }
  }, [count]); // count๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

export default GoodCounter;

  • useState ํ›…๊ณผ useEffect ํ›…์€ ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜์˜ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ ํ˜ธ์ถœ๋˜์—ˆ๋‹ค.
  • Hook ํ˜ธ์ถœ์ด ํ•ญ์ƒ ๋™์ผํ•œ ์œ„์น˜์— ์žˆ์–ด์„œ React๊ฐ€ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๊ทœ์น™์„ ๊ฐ•์ œํ•˜๋Š” ํ”Œ๋กœ๊ทธ์ธ

 

npm ๋ฐ”๋กœ๊ฐ€๊ธฐ

eslint-plugin-react-hooks

์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ Create React App์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

npm install eslint-plugin-react-hooks --save-dev
// ESLint ์„ค์ • ํŒŒ์ผ
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
    "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
  }
}

 

 

Hooks๋Š” ์™œ ๋„์ž…๋˜์—ˆ์„๊นŒ?

 

<Class /> ๊ธฐ์กด์˜ ๋ฆฌ์•กํŠธ๋Š” ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์—…ํ–ˆ๋‹ค.

๋‹น์‹œ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์กด์žฌํ–ˆ์ง€๋งŒ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์— ๋น„ํ•ด ๊ธฐ๋Šฅ์ด ์ ์—ˆ๋‹ค.

 

 

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๋‹จ์ 

 

this

  • this๋Š” ํด๋ž˜์Šค ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ด
  • this๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๊ณ  ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ
  • ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋˜๋ฉด์„œ this๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด ๊ณ ์ •๋˜์ง€ ์•Š๋Š” this๋กœ ์ธํ•ด ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

 

์žฌ์‚ฌ์šฉ์„ฑ

  • ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ์ง€ ์•Š๋‹ค.
  • HOC ํŒจํ„ด๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ–ˆ์ง€๋งŒ ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • HOC๋ผ๋Š” ๊ณ ์ฐจ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์ง€๋งŒ Wrapper ์ง€์˜ฅ์ด๋ผ๋Š” ์ปค๋‹ค๋ž€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

 

 

๋–จ์–ด์ง€๋Š” ๊ฐ€๋…์„ฑ

์ดˆ๊ธฐ๊ฐ’์ด 0์ธ count ์ƒํƒœ๋ฅผ ์„ ์–ธํ•˜๊ณ , ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด count + 1 ๋˜๋Š” ๊ฐ„๋‹จํ•œ ๋กœ์ง์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ

 

 

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ

class Example extends React.Component {
  constructor(props) {
  	super(props);
    this.state = {
      count: 0,
    }
  }
  
  handleClick() {
  	this.setState({ count: this.state.count + 1});
  }
  
  render() {
  	return {
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick.bind(this)}>Click me</button>
      </div>
    }
  }
}

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

 

ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ

const Example = () => {
  const [count, setCount] = React.useState(0);
  
  const handleClick = () => {
  	setCount(count + 1);
  }
  
  return {
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  }
}
  • ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์— ๋น„ํ•ด ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Hook์„ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ์™€ ์ƒํƒœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•„์ˆ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ๋˜ this์˜ ๋ฌธ์ œ๋กœ๋ถ€ํ„ฐ ํ•ด๋ฐฉ๋œ ๋ชจ์Šต๋„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

HOC(Higher Order Component)๋ž€?

 

  • Higher Order Component (๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ)
  • ํ™”๋ฉด์—์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด์„œ ์ปดํฌ๋„ŒํŠธ๋กœ ๋งŒ๋“ค๊ณ , ์žฌ์‚ฌ์šฉ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„์€ parameter๋กœ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

 

// ์‚ฌ์šฉ์ž์˜ ๋‚˜์ด ์ •๋ณด ํŽ˜์ด์ง€

class UserProfile extends React.Component {
  state = {
    users: [],
  };

  componentDidMount() {
    fetchUsers().then((users) => {
      this.setState({ users });
    });
  }

  render() {
    const { users } = this.state;
   
   return (
      <div>
        {users.map(({ name, job }) => (
          <div key={name}>
            <p>{name}: {job}</<p>
          </div>
        ))}
      </div>
    );
  }
}

 

// ์‚ฌ์šฉ์ž์˜ ์ง์—… ์ •๋ณด ํŽ˜์ด์ง€

class UserJobPage extends React.Component {
  state = {
    users: [],
  };

  componentDidMount() {
    fetchUsers().then((users) => {
      this.setState({ users });
    });
  }

  render() {
    const { users } = this.state;
    
    return (
      <div>
        <p>์‚ฌ์šฉ์ž์˜ ์ง์—… ํŽ˜์ด์ง€</p>
        {users.map(({ name, job }) => (
          <div key={name}>
            <p>{name}: {job}</p>
          </div>
        ))}
      </div>
    );
  }
}
  • ๋‘ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ Œ๋”๋ง ํ•˜๋Š” ๋กœ์ง๋งŒ ์กฐ๊ธˆ ๋‹ค๋ฅด๊ณ , ์œ ์ € ์ •๋ณด๋ฅผ fetch ํ•ด์™€์„œ ์ƒํƒœ๋กœ ์ €์žฅํ•˜๋Š” ๋กœ์ง์€ ๋™์ผํ•˜๋‹ค.

 

// ์œ ์ € fetching ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” HOC

function usersHOC(Component) {
  return class extends React.Component {
    state = { 
    	users: [] 
    };

    componentDidMount() {
      	fetchUsers().then((users) => {
      		this.setState({ users });
    	});
    }

    render() {
      return <Component {...this.props} {...this.state} />;
    }
  };
}
  • ์ค‘๋ณต๋œ ์œ ์ € fetching ๋กœ์ง์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ
  • usersHOC๋ผ๋Š” ๊ณ ์ฐจ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.
  • ๋‘ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ๋˜ ์œ ์ € fetching ๋กœ์ง์„ usersHOC ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ

 

function usersHOC(Component) {  // ์ธ์ž๋กœ ์ปดํฌ๋„ŒํŠธ ์ „๋‹ฌ
  return class extends React.Component {
    state = { 
    	users: [] 
    };

    componentDidMount() {
      	fetchUsers().then((users) => {
      		this.setState({ users })
        });
    }

    render() {
      return <Component {...this.props} {...this.state} />;  <!-- ์ปดํฌ๋„ŒํŠธ์˜ props๋กœ ์œ ์ € state ์ „๋‹ฌ -->
    }
  };
}
  • usersHOC ์ปดํฌ๋„ŒํŠธ๋Š” ์œ ์ € fetching ๋กœ์ง์„ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ณ ,
  • ์ธ์ž๋กœ ๋ฐ›์€ ์ปดํฌ๋„ŒํŠธ์— users state๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.

 

// ๊ฐ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ๋Š” usersHOC๋ฅผ ๊ฐ์‹ธ์„œ ์‚ฌ์šฉํ•œ๋‹ค.

function UserAgePage({ users }) {
  // ... ์—ฌ๊ธฐ์— UserAgePage ์ปดํฌ๋„ŒํŠธ์˜ ๋กœ์ง์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค ...
}

export default usersHOC(UserAgePage);
// ๊ฐ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ๋Š” usersHOC๋ฅผ ๊ฐ์‹ธ์„œ ์‚ฌ์šฉํ•œ๋‹ค.

function UserJobPage({ users }) {
  // ... ์—ฌ๊ธฐ์— UserJobPage ์ปดํฌ๋„ŒํŠธ์˜ ๋กœ์ง์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค ...
}

export default usersHOC(UserJobPage);
  • ๊ฐ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ์—๋Š” usersHOC ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ๋ฉด ์œ ์ œ ํŽ˜์นญ ๋กœ์ง์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

HOC ํŒจํ„ด์˜ ๋ฌธ์ œ์  : Wrapper ์ง€์˜ฅ

 

HOC ํŒจํ„ด์€ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ์œ„ํ•ด ์ถ”์ฒœ๋˜๋Š” ํŒจํ„ด์ด์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ HOC ํŒจํ„ด์—๋Š” Wrapper ์ง€์˜ฅ์ด๋ผ๋Š” ์ปค๋‹ค๋ž€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

 

<ThemeHOC>
  <UserHOC>
    <AuthHOC>
	  <MyComponent />
    </AuthHOC>
  </UserHOC>
</ThemeHOC>

 

MyComponent์— ํ…Œ๋งˆ ๋กœ์ง, ์œ ์ € ๊ด€๋ จ ๋กœ์ง, ์ธ์ฆ ๋กœ์ง์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ๊ณ ์ฐจ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฐ์‹ธ์คฌ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ณ„์†ํ•ด์„œ ๊ฐ์‹ธ๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ depth๊ฐ€ ์—„์ฒญ ๊นŠ์–ด์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์ด๋ฅผ Wrapper ์ง€์˜ฅ์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

 

Hook์˜ Life Cycle

 

Hooks๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด ์ƒ๋ช… ์ฃผ๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ๋งŽ์ด ๋ณ€ํ•˜๊ฒŒ ๋œ๋‹ค.

 

  • Mount : ์ฒ˜์Œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ๋ Œ๋”๋ง์„ ๊ฑฐ์น˜๋Š” ๊ณผ์ •์„ ์˜๋ฏธ
    • ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” componentDidMount() ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰

 

  • Update : props ํ˜น์€ state๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ, forceUpdate() ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์—ˆ์„ ๋•Œ ๋ฆฌ๋ Œ๋”๋ง ํ•˜๋Š” ๊ณผ์ •์„ ์˜๋ฏธ
    • ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” componentDidUpdate() ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰

 

  • Unmount : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ๊ณผ์ •์„ ์˜๋ฏธ
    • ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” componentWillUnmount() ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰

 

Hooks๊ฐ€ ๋“ฑ์žฅํ•œ ์ดํ›„๋ถ€ํ„ฐ๋Š” ์•ž์„œ ๋งํ•œ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ ๋Œ€ํ‘œ์ ์ธ ์ƒ๋ช… ์ฃผ๊ธฐ ํ•จ์ˆ˜ ์„ธ ๊ฐ€์ง€๋ฅผ useEffect() ํ•จ์ˆ˜ ํ•˜๋‚˜๋กœ ๋ชจ๋‘ ์ปค๋ฒ„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

 

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ

componentDidMount() {
  this.updateList(this.props.id);
}

componentDidUpdate() {
  if(prevProps.id === this.props.id) return;
  
  this.updateList(this.props.id);
}

Mount ๋  ๋•Œ updateList() ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ๋˜ props id๊ฐ€ ์—…๋ฐ์ดํŠธ๋  ๋•Œ updateList() ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ ์ฝ”๋“œ

 

Hooks๋ฅผ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ

useEffect(() => {
  updateList(id);
}, [id]);

useEffect() ํ›… ํ•˜๋‚˜๋กœ ๋‘ ๊ฐ€์ง€ ๋ผ์ดํ”„ ์‚ฌ์ดํด ํ•จ์ˆ˜์˜ ๊ธฐ๋Šฅ์„ ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ

componentDidMount() {
  document.body.style.overflow = 'hidden';
}

conponentWillUnmount() {
  document.body.style.removeProperty('overflow');
}

์ปดํฌ๋„ŒํŠธ๊ฐ€ Mount ๋  ๋•Œ ์Šคํฌ๋กค ๋ฐฉ์ง€ ์Šคํƒ€์ผ์„ ์ถ”๊ฐ€ํ•˜๊ณ , Unmount ๋  ๋•Œ ์Šคํฌ๋กค ๋ฐฉ์ง€ ์Šคํƒ€์ผ์„ ๋‹ค์‹œ ์—†์• ์ฃผ๋Š” ์ฝ”๋“œ์ด๋‹ค.

 

Hooks๋ฅผ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ

useEffect(()=> {
  document.body.style.overflow = "hidden";
  
  return () => document.body.style.removeProperty("overflow");
}, []);

useEffect() ํ•จ์ˆ˜ ํ•˜๋‚˜ ๋‚ด์—์„œ Mount, Unmount ๋‘ ๊ฐ€์ง€ ์ƒ๋ช… ์ฃผ๊ธฐ์— ๋Œ€ํ•œ ๋กœ์ง์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

 

Custom Hook

 

Custom Hook์ด๋ž€ useState, useEffect์™€ ๊ฐ™์ด ๋ฆฌ์•กํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” Hook๋“ค์„ ์ด์šฉํ•ด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋งŒ๋“œ๋Š” Hook์„ ์˜๋ฏธํ•œ๋‹ค.

 

์ƒํƒœ ๊ด€๋ฆฌ๋‚˜ ์ƒ๋ช… ์ฃผ๊ธฐ ๋กœ์ง๋“ค์„ ์ถ”์ƒํ™”ํ•˜์—ฌ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ๋œปํ•œ๋‹ค.

 

HOCํŒจํ„ด์œผ๋กœ ๋งŒ๋“  ์œ ์ € fetching ๋กœ์ง์„ Custom Hook์œผ๋กœ ๋งŒ๋“ ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

const useFetchUser = () => {
  const [users, setUsers] = useState([]);
  
  useEffect(()=> {
    fetchUsers().then((users) => {
      setUsers(users);
    });
  }, []);
  
  return { users };
}
  • usersHOC ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค๋Š” ํ›จ์”ฌ ๊ฐ„๋‹จํ•˜๊ณ  ์ฝ๊ธฐ ์‰ฝ๋‹ค.
  • users๋ผ๋Š” ์ƒํƒœ๋ฅผ ์„ ์–ธํ•˜๊ณ , useEffect๋ฅผ ์‚ฌ์šฉํ•ด ์ฒ˜์Œ ๋งˆ์šดํŠธ ๋  ๋•Œ fetchUsers ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

 

const UserAgePage = () => {
  const { users } = useFetchUser();
  
  return(
    ...
  • useFetchUser ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋‹จ ํ•œ ์ค„๋งŒ ์ถ”๊ฐ€ํ•ด ์ฃผ๋ฉด ์‰ฝ๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • Wrapper ์ง€์˜ฅ๊ฐ™์ด ๊ณจ์น˜ ์•„ํ”ˆ ๋ฌธ์ œ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

 

 

์ €์ž‘์žํ‘œ์‹œ (์ƒˆ์ฐฝ์—ด๋ฆผ)

'Frontend > React' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

React Router: push์™€ replace์˜ ์ฐจ์ด์   (0) 2024.10.15
React Hook Form์˜ handleSubmit์œผ๋กœ ํผ ์ œ์ถœ ์‹œ ํŽ˜์ด์ง€ ๋ฆฌ๋ Œ๋”๋ง ๋ฐฉ์ง€ํ•˜๊ธฐ  (0) 2024.09.26
React Router v6  (0) 2024.09.26
React์—์„œ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๋Š” ์กฐ๊ฑด๊ณผ ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•  (0) 2024.05.09
๋ฆฌ์•กํŠธ๋ฒ„์ „ 18๋ถ€ํ„ฐ ๋“ฑ์žฅํ•˜๋Š” Batching ๊ฐœ๋…  (0) 2024.05.03
    'Frontend/React' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • React Hook Form์˜ handleSubmit์œผ๋กœ ํผ ์ œ์ถœ ์‹œ ํŽ˜์ด์ง€ ๋ฆฌ๋ Œ๋”๋ง ๋ฐฉ์ง€ํ•˜๊ธฐ
    • React Router v6
    • React์—์„œ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๋Š” ์กฐ๊ฑด๊ณผ ๋ Œ๋”๋ง ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•
    • ๋ฆฌ์•กํŠธ๋ฒ„์ „ 18๋ถ€ํ„ฐ ๋“ฑ์žฅํ•˜๋Š” Batching ๊ฐœ๋…
    wam
    wam

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”