๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

javascript/[TIL] ๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ 

๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ  - Hooks

728x90

1. useState

2. useEffect

3. useReducer

4. useMemo

5. useCallBack

6. useRef

7. ์ปค์Šคํ…€ Hooks

 

useEffect ใ€€VSใ€€useCallBack ใ€€VS ใ€€useMemo

useEffect useCallBack useMemo
ํŠน์ •๊ฐ’(๋ฐฐ์—ด ์•ˆ ๊ฐ’)์ด ์—…๋ฐ์ดํŠธ ๋ ๋•Œ,
ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค์ •

์ƒˆ๋กœ์šด ํ•จ์ˆ˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์‹คํ–‰๋˜๋Š”์ง€ ์—ฌ๋ถ€์™€ ๊ด€๋ จ

ํŠน์ •๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ,
ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑ,

ํ•จ์ˆ˜ memoizationํ•˜์—ฌ,
๊ฐ™์€ ํ•จ์ˆ˜ ์ธ์Šคํ„ด์Šค ์žฌ์‚ฌ์šฉ

โ€ป ๋นˆ ๋ฐฐ์—ด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ ๋งŒ๋“ค์—ˆ๋˜ ํ•จ์ˆ˜๋ฅผ ๊ณ„์†ํ•ด์„œ ์žฌ์‚ฌ์šฉ
ํŠน์ •๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ,
์—ฐ์‚ฐ์„ ์‹คํ–‰(o)
์ƒˆ๋กœ ์ƒ์„ฑ(x)

๊ฐ’์„ memoizationํ•˜์—ฌ,
๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋‚˜ ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉ

์›ํ•˜๋Š” ๊ฐ’์ด ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด์ „ ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์‚ฌ์šฉ
(==๋ฉ”๋ชจ์ด์ฆˆ ๋œ ๊ฐ’์„ return)

Hooks๋Š” ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ(useState, useEffect ๋“ฑ) ์„ ์ œ๊ณตํ•œ๋‹ค.

( ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ์ƒํƒœ๊ด€๋ฆฌ์˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„)

 

1. useState

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

 

2. useEffect

์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋นˆ ๋ฐฐ์—ด [ ] : ๋งจ ์ฒ˜์Œ ๋ Œ๋”๋ง ๋ ๋•Œ๋งŒ ์‹คํ–‰ํ•˜๊ณ , ์—…๋ฐ์ดํŠธ๋  ๋•Œ๋Š” ์‹คํ–‰ํ•˜์ง€ ์•Š์Œ.

ํŠน์ •๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„๋•, ๋ฐฐ์—ด ์•ˆ์— ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ์€ ๊ฐ’์„ ๋„ฃ์–ด์ค€๋‹ค.

useEffect(()=>{
	console.log(name);
}, [name]);

 

3. useReducer - useReducer('reducer' , ํ•ด๋‹น ๋ฆฌ๋“€์„œ์˜ ๊ธฐ๋ณธ๊ฐ’);

๋” ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ์ƒํƒœ๋ฅผ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ด ์ฃผ๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

'reducer'๋Š” (ํ˜„์žฌ ์ƒํƒœ, ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ action๊ฐ’)์„ ์ธ์ž๋กœ ์ „๋‹ฌ๋ฐ›์•„ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

์ปดํฌ๋„ŒํŠธ ์—…๋ฐ์ดํŠธ ๋กœ์ง์„ ์ปดํฌ๋„ŒํŠธ ๋ฐ”๊นฅ์œผ๋กœ ๋นผ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

Nickname.js

import
{ useEffect, useState } from "react";

const Nickname = () => {
  const [name, setName] = useState("");
  const [nickname, setNickName] = useState("");
 

  // ํŠน์ • ๊ฐ’('name')์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„๋•Œ,
  // useEffect์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ฐฐ์—ด ์•ˆ์— ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ์€ ๊ฐ’ ์ž…๋ ฅ(['name'])
  useEffect(() => {
    console.log("effect");
    console.log({ name, nickname });


    // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ ๋˜๊ธฐ์ „, ์—…๋ฐ์ดํŠธ ๋˜๊ธฐ ์ง์ „์— ์–ด๋– ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์„๋•Œ,
    // ๋’ท์ •๋ฆฌ ํ•จ์ˆ˜๋ฅผ "๋ฐ˜ํ™˜(return)" ํ•ด ์ฃผ์–ด์•ผ ํ•จ.
    return () => {
      console.log("cleanup");
      console.log({ name, nickname });
    };
  }, [name]);

  const changeName = (e) => {
    setName(e.target.value);
  };

  const changeNickName = (e) => {
    setNickName(e.target.value);
  };

  return (
    <>
      <input onChange={changeName} value={name} />
      <input onChange={changeNickName} value={nickname} />
      <p> ์ด๋ฆ„ {name}</p>
      <p> ๋‹‰๋„ค์ž„ {nickname}</p>
    </>
  );
};
export default Nickname;
Nickname_useReducer.js

import { useReducer } from "react";

// ์ปดํฌ๋„ŒํŠธ ์—…๋ฐ์ดํŠธ ๋กœ์ง์„ ์ปดํฌ๋„ŒํŠธ ๋ฐ”๊นฅ์œผ๋กœ ๋นผ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
function reducer(state, action) {
  return {
    ...state,
    [action.name]: action.value,
  };
}

const Nickname_useReducer = () => {
  // useReducer ์ด Hook์„ ์‚ฌ์šฉํ•˜๋ฉด state๊ฐ’๊ณผ dispatch ํ•จ์ˆ˜๋ฅผ ๋ฐ›์•„์˜ด.
  // state - ํ˜„์žฌ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ์ƒํƒœ
  // dispatch - ์•ก์…˜์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ํ•จ์ˆ˜๋กœ, ํ•จ์ˆ˜ ์•ˆ์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์•ก์…˜ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉด 'reducer'ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ
  // dispathch(e.target) -> reducer(state, e.target)

  const [state, dispatch] = useReducer(reducer, { name: "", nickname: "" });

  const { name, nickname } = state;

  const onChange = (e) => {
    dispatch(e.target);
  };

  return (
    <>
      <p>useReducer</p>
      <input onChange={onChange} value={name} name="name" />
      <input onChange={onChange} value={nickname} name="nickname" />
      <p> ์ด๋ฆ„ {name}</p>
      <p> ๋‹‰๋„ค์ž„ {nickname}</p>
    </>
  );
};
export default Nickname_useReducer;

 

 

4. useMemo

: ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์—ฐ์‚ฐ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ Œ๋”๋งํ•˜๋Š” ๊ณผ์ •์—์„œ ํŠน์ • ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ๋งŒ ์—ฐ์‚ฐ์„ ์‹คํ–‰ํ•˜๊ณ ,

์›ํ•˜๋Š” ๊ฐ’์ด ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด์ „ ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์‚ฌ์šฉ

(==๋ฉ”๋ชจ์ด์ฆˆ ๋œ ๊ฐ’์„ return)

 

5. useCallBack - useCallBack(์ƒ์„ฑํ•˜๊ณ  ์‹ถ์€ ํ•จ์ˆ˜, ๋ฐฐ์—ด)

โ†—์ด ๋ฐฐ์—ด์—๋Š” ์–ด๋–ค ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š”์ง€ ๋ช…์‹œ,

ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ƒํƒœ ๊ฐ’์— ์˜์กดํ•ด์•ผ ํ•  ๋•Œ๋Š” ๊ทธ ๊ฐ’์„ ๋ฐ˜๋“œ์‹œ ๋ฐฐ์—ด์•ˆ์— ํฌํ•จํ•ด์•ผํ•จ.

โ€ป ๋น„์–ด์žˆ๋Š” ๋ฐฐ์—ด์„ ๋„ฃ๊ฒŒ ๋˜๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ ๋งŒ๋“ค์—ˆ๋˜ ํ•จ์ˆ˜๋ฅผ ๊ณ„์†ํ•ด์„œ ์žฌ์‚ฌ์šฉ

:useMemo์™€ ๋น„์Šท, ์ด Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ๋งŒ๋“ค์–ด ๋†จ๋˜ ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ๋ Œ๋”๋ง ์„ฑ๋Šฅ์„ ์ตœ์ ํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

6. useRef

: ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ref๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

๋˜ํ•œ ์„ฑ๋Šฅ์„ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด id ๊ฐ’์€ ํ™”๋ฉด์— ๋ณด์ด์ง€๋„ ์•Š๊ณ , ์ด ๊ฐ’์ด ๋ฐ”๋€๋‹ค๊ณ  ํ•ด์„œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค.

๋‹จ์ˆœํžˆ ์ƒˆ๋กœ์šด ํ•ญ๋ชฉ์„ ๋งŒ๋“ค๋•Œ ์ฐธ์กฐ๋˜๋Š” ๊ฐ’์ด๋ฏ€๋กœ ๋ Œ๋”๋ง๋˜๋Š” ์ •๋ณด๊ฐ€ ์•„๋‹ˆ๋‹ค. 

 

import { useCallback, useMemo, useState, useRef } from 'react';

function getAverage(numbers) {
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
}

const Average = () => {
  const [number, setNum] = useState(0);
  const [list, setList] = useState([]);

  const InputEL = useRef(null);

  const onChange = useCallback((e) => {
    setNum(e.target.value);
  }, []);

  const onInsert = useCallback(() => {
    const newList = list.concat(parseInt(number));
    setList(newList);
    setNum('');
    InputEL.current.focus();
  }, [number, list]);

  const avg = useMemo(() => getAverage(list), [list]);

  return (
    <>
      <input onChange={onChange} ref={InputEL} />
      <button onClick={onInsert}>๋“ฑ๋ก</button>
      <ul>
        {list.map((e, i) => (
          <li key={i}>{e}</li>
        ))}
      </ul>
      <p>ํ‰๊ท ๊ฐ’ : {avg}</p>
    </>
  );
};

export default Average;

 


7. ์ปค์Šคํ…€ Hooks ๋งŒ๋“ค๊ธฐ

์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ๊ณต์œ ํ•  ๊ฒฝ์šฐ, ์ด๋ฅผ ์—ฌ๋Ÿฌ๋ถ„๋งŒ์˜ Hook์œผ๋กœ ์ž‘์„ฑํ•˜์—ฌ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

728x90