We want to hear from you!Take our 2021 Community Survey!
Support Ukraine ๐Ÿ‡บ๐Ÿ‡ฆ Help Provide Humanitarian Aid to Ukraine.

Hooks API Reference

Hook๋Š” React 16.8์—์„œ ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. Hook์„ ํ†ตํ•ด class๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ state์™€ ๊ฐ™์€ React ๊ธฐ๋Šฅ๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๋Š” React์— ๋‚ด์žฅ๋œ Hook API๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

Hook์ด ์ƒ์†Œํ•˜๋‹ค๋ฉด Hook ๊ฐœ์š”๋ฅผ ๋จผ์ € ์ฝ์–ด ๋ณด๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. ํ˜น์€ frequently asked questions์—์„œ ์œ ์šฉํ•œ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ Hook

useState

const [state, setState] = useState(initialState);

์ƒํƒœ ์œ ์ง€ ๊ฐ’๊ณผ ๊ทธ ๊ฐ’์„ ๊ฐฑ์‹ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ตœ์ดˆ๋กœ ๋ Œ๋”๋ง์„ ํ•˜๋Š” ๋™์•ˆ, ๋ฐ˜ํ™˜๋œ state(state)๋Š” ์ฒซ ๋ฒˆ์งธ ์ „๋‹ฌ๋œ ์ธ์ž(initialState)์˜ ๊ฐ’๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

setState ํ•จ์ˆ˜๋Š” state๋ฅผ ๊ฐฑ์‹ ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ state ๊ฐ’์„ ๋ฐ›์•„ ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง์„ ํ์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

setState(newState);

๋‹ค์Œ ๋ฆฌ๋ Œ๋”๋ง ์‹œ์— useState๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜๋ฐ›์€ ์ฒซ ๋ฒˆ์งธ ๊ฐ’์€ ํ•ญ์ƒ ๊ฐฑ์‹ ๋œ ์ตœ์‹  state๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

์ฃผ์˜

React๋Š” setState ํ•จ์ˆ˜ ๋™์ผ์„ฑ์ด ์•ˆ์ •์ ์ด๊ณ  ๋ฆฌ๋ Œ๋”๋ง ์‹œ์—๋„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด useEffect๋‚˜ useCallback ์˜์กด์„ฑ ๋ชฉ๋ก์— ์ด ํ•จ์ˆ˜๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์•„๋„ ๋ฌด๋ฐฉํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค.

ํ•จ์ˆ˜์  ๊ฐฑ์‹ 

์ด์ „ state๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒˆ๋กœ์šด state๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒฝ์šฐ ํ•จ์ˆ˜๋ฅผ setState ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ํ•จ์ˆ˜๋Š” ์ด์ „ ๊ฐ’์„ ๋ฐ›์•„ ๊ฐฑ์‹ ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— setState์˜ ์–‘์ชฝ ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ•œ ์นด์šดํ„ฐ ์ปดํฌ๋„ŒํŠธ์˜ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

โ€+โ€œ์™€ โ€-โ€ ๋ฒ„ํŠผ์€ ํ•จ์ˆ˜ ํ˜•์‹์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฐฑ์‹ ๋œ ๊ฐ’์ด ๊ฐฑ์‹ ๋˜๊ธฐ ์ด์ „์˜ ๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ณ„์‚ฐ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, โ€œResetโ€ ๋ฒ„ํŠผ์€ ์นด์šดํŠธ๋ฅผ ํ•ญ์ƒ 0์œผ๋กœ ์„ค์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ฐ˜์ ์ธ ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜๊ฐ€ ํ˜„์žฌ ์ƒํƒœ์™€ ์ •ํ™•ํžˆ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋ฉด ๋ฐ”๋กœ ๋’ค์— ์ผ์–ด๋‚  ๋ฆฌ๋ Œ๋”๋ง์€ ์™„์ „ํžˆ ๊ฑด๋„ˆ๋›ฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ฃผ์˜

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ setState ๋ฉ”์„œ๋“œ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, useState๋Š” ๊ฐฑ์‹  ๊ฐ์ฒด(update objects)๋ฅผ ์ž๋™์œผ๋กœ ํ•ฉ์น˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์—…๋ฐ์ดํ„ฐ ํผ์„ ๊ฐ์ฒด ์ „๊ฐœ ์—ฐ์‚ฐ์ž์™€ ๊ฒฐํ•ฉํ•จ์œผ๋กœ์จ ์ด ๋™์ž‘์„ ๋ณต์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const [state, setState] = useState({});
setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” useReducer๊ฐ€ ์žˆ๋Š”๋ฐ ์ด๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ•˜์œ—๊ฐ’๋“ค์„ ํฌํ•จํ•œ state ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ์— ๋” ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

์ง€์—ฐ ์ดˆ๊ธฐ state

initialState ์ธ์ž๋Š” ์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ์— ์‚ฌ์šฉํ•˜๋Š” state์ž…๋‹ˆ๋‹ค. ๊ทธ ์ดํ›„์˜ ๋ Œ๋”๋ง ์‹œ์—๋Š” ์ด ๊ฐ’์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐ state๊ฐ€ ๊ณ ๋น„์šฉ ๊ณ„์‚ฐ์˜ ๊ฒฐ๊ณผ๋ผ๋ฉด, ์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ์—๋งŒ ์‹คํ–‰๋  ํ•จ์ˆ˜๋ฅผ ๋Œ€์‹  ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

state ๊ฐฑ์‹ ์˜ ์ทจ์†Œ

State Hook์„ ํ˜„์žฌ์˜ state์™€ ๋™์ผํ•œ ๊ฐ’์œผ๋กœ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒฝ์šฐ React๋Š” ์ž์‹์„ ๋ Œ๋”๋ง ํ•œ๋‹ค๊ฑฐ๋‚˜ ๋ฌด์—‡์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ํšŒํ”ผํ•˜๊ณ  ๊ทธ ์ฒ˜๋ฆฌ๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. (React๋Š” Object.is ๋น„๊ต ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.)

์‹คํ–‰์„ ํšŒํ”ผํ•˜๊ธฐ ์ „์— React์—์„œ ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜์„ธ์š”. React๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํŠธ๋ฆฌ์— ๊ทธ ์ด์ƒ์œผ๋กœ ใ€Œ๋” ๊นŠ๊ฒŒใ€๋Š” ๊ด€์—ฌํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ฏ€๋กœ ํฌ๊ฒŒ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์œผ์…”๋„ ๋ฉ๋‹ˆ๋‹ค๋งŒ, ๋ Œ๋”๋ง ์‹œ์— ๊ณ ๋น„์šฉ์˜ ๊ณ„์‚ฐ์„ ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด useMemo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ๊ฒƒ๋“ค์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

useEffect

useEffect(didUpdate);

๋ช…๋ นํ˜• ๋˜๋Š” ์–ด๋–ค effect๋ฅผ ๋ฐœ์ƒํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.

๋ณ€ํ˜•, ๊ตฌ๋…, ํƒ€์ด๋จธ, ๋กœ๊น… ๋˜๋Š” ๋‹ค๋ฅธ ๋ถ€์ž‘์šฉ(side effects)์€ (React์˜ ๋ Œ๋”๋ง ๋‹จ๊ณ„์— ๋”ฐ๋ฅด๋ฉด) ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์˜ ๋ณธ๋ฌธ ์•ˆ์—์„œ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ๋งค์šฐ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ฒ„๊ทธ ๋ฐ UI์˜ ๋ถˆ์ผ์น˜๋ฅผ ์•ผ๊ธฐํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋Œ€์‹ ์— useEffect๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. useEffect์— ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๋Š” ํ™”๋ฉด์— ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋œ ํ›„์— ์ˆ˜ํ–‰๋˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. React์˜ ์ˆœ์ˆ˜ํ•œ ํ•จ์ˆ˜์ ์ธ ์„ธ๊ณ„์—์„œ ๋ช…๋ น์ ์ธ ์„ธ๊ณ„๋กœ์˜ ํƒˆ์ถœ๊ตฌ๋กœ ์ƒ๊ฐํ•˜์„ธ์š”.

๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์ž‘์€ ๋ชจ๋“  ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋œ ํ›„์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค๋งŒ, ์–ด๋–ค ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ๋งŒ ์‹คํ–‰๋˜๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

effect ์ •๋ฆฌ

effect๋Š” ์ข…์ข… ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์—์„œ ์ œ๊ฑฐ๋  ๋•Œ ์ •๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ฐ€๋ น ๊ตฌ๋…์ด๋‚˜ ํƒ€์ด๋จธ ID์™€ ๊ฐ™์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ useEffect๋กœ ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๋Š” ์ •๋ฆฌ(clean-up) ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ตฌ๋…์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // Clean up the subscription
    subscription.unsubscribe();
  };
});

์ •๋ฆฌ ํ•จ์ˆ˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด UI์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์ „์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋”๋ถˆ์–ด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ (๊ทธ๋ƒฅ ์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ) ์—ฌ๋Ÿฌ ๋ฒˆ ๋ Œ๋”๋ง ๋œ๋‹ค๋ฉด ๋‹ค์Œ effect๊ฐ€ ์ˆ˜ํ–‰๋˜๊ธฐ ์ „์— ์ด์ „ effect๋Š” ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์—์„œ, ๋งค ๊ฐฑ์‹ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ตฌ๋…์ด ์ƒ์„ฑ๋œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐฑ์‹ ๋งˆ๋‹ค ๋ถˆํ•„์š”ํ•œ ์ˆ˜ํ–‰์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ํšŒํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ ์ ˆ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

effect ํƒ€์ด๋ฐ

componentDidMount์™€ componentDidUpdate์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, useEffect๋กœ ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๋Š” ์ง€์—ฐ ์ด๋ฒคํŠธ ๋™์•ˆ์— ๋ ˆ์ด์•„์›ƒ ๋ฐฐ์น˜์™€ ๊ทธ๋ฆฌ๊ธฐ๋ฅผ ์™„๋ฃŒํ•œ ํ›„ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ตฌ๋…์ด๋‚˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋‹ค์ˆ˜์˜ ๊ณตํ†ต์ ์ธ ๋ถ€์ž‘์šฉ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒ๋ฉด ๋Œ€๋ถ€๋ถ„์˜ ์ž‘์—…์ด ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ™”๋ฉด์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์„ ์ฐจ๋‹จํ•ด์„œ๋Š” ์•ˆ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€๋งŒ, ๋ชจ๋“  effect๊ฐ€ ์ง€์—ฐ๋  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœ๋˜๋Š” DOM ๋ณ€๊ฒฝ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋…ธ์ถœ๋œ ๋‚ด์šฉ์˜ ๋ถˆ์ผ์น˜๋ฅผ ๊ฒฝํ—˜ํ•˜์ง€ ์•Š๋„๋ก ๋‹ค์Œ ํ™”๋ฉด์„ ๋‹ค ๊ทธ๋ฆฌ๊ธฐ ์ด์ „์— ๋™๊ธฐํ™” ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (๊ทธ ๊ตฌ๋ถ„์ด๋ž€ ๊ฐœ๋…์ ์œผ๋กœ๋Š” ์ˆ˜๋™์  ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์™€ ๋Šฅ๋™์  ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์˜ ์ฐจ์ด์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค) ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ effect๋ฅผ ์œ„ํ•ด React๋Š” useLayoutEffect๋ผ๋Š” ์ถ”๊ฐ€์ ์ธ Hook์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ useEffect์™€ ๋™์ผํ•œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ๊ทธ๊ฒƒ์ด ์ˆ˜ํ–‰๋  ๋•Œ์—๋งŒ ์ฐจ์ด๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค.

useEffect๋Š” ๋ธŒ๋ผ์šฐ์ € ํ™”๋ฉด์ด ๋‹ค ๊ทธ๋ ค์งˆ ๋•Œ๊นŒ์ง€ ์ง€์—ฐ๋ฉ๋‹ˆ๋‹ค๋งŒ, ๋‹ค์Œ ์–ด๋–ค ์ƒˆ๋กœ์šด ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๊ธฐ ์ด์ „์— ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ๋„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. React๋Š” ์ƒˆ๋กœ์šด ๊ฐฑ์‹ ์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ด์ „ ๋ Œ๋”๋ง์„ ํ•ญ์ƒ ์™„๋ฃŒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์กฐ๊ฑด๋ถ€ effect ๋ฐœ์ƒ

effect์˜ ๊ธฐ๋ณธ ๋™์ž‘์€ ๋ชจ๋“  ๋ Œ๋”๋ง์„ ์™„๋ฃŒํ•œ ํ›„ effect๋ฅผ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ์˜์กด์„ฑ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด effect๋Š” ํ•ญ์ƒ ์žฌ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์ด์ „ ์„น์…˜์˜ ๊ตฌ๋… ์˜ˆ์‹œ์™€ ๊ฐ™์ด ์ผ๋ถ€ ๊ฒฝ์šฐ์—๋Š” ๊ณผ๋„ํ•œ ์ž‘์—…์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. source props๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ์—๋งŒ ํ•„์š”ํ•œ ๊ฒƒ์ด๋ผ๋ฉด ๋งค๋ฒˆ ๊ฐฑ์‹ ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ตฌ๋…์„ ์ƒ์„ฑํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” useEffect์— ๋‘ ๋ฒˆ์งธ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜์„ธ์š”. ์ด ์ธ์ž๋Š” effect๊ฐ€ ์ข…์†๋˜์–ด ์žˆ๋Š” ๊ฐ’์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์ ์šฉํ•œ ์˜ˆ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

์ž ์ด์ œ, props.source๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ์—๋งŒ ๊ตฌ๋…์ด ์žฌ์ƒ์„ฑ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฃผ์˜

์ด ์ตœ์ ํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๊ฐ’์˜ ๋ฐฐ์—ด์ด ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋˜๊ณ  effect์— ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋ฒ”์œ„์˜ ๋ชจ๋“  ๊ฐ’๋“ค(์˜ˆ๋ฅผ ๋“ค์–ด, props์™€ state์™€ ๊ฐ™์€ ๊ฐ’๋“ค)์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋“œ๋Š” ์ด์ „ ๋ Œ๋”๋ง์—์„œ ์„ค์ •๋œ ์˜ค๋ž˜๋œ ๊ฐ’์„ ์ฐธ์กฐํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. how to deal with functions์™€ array values change too often ํ•  ๋•Œ ๋ฌด์—‡์„ ํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•ด์„œ ์กฐ๊ธˆ ๋” ์•Œ์•„๋ณด์„ธ์š”.

effect๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  (mount๋ฅผ ํ•˜๊ฑฐ๋‚˜ unmount ํ•  ๋•Œ) ๊ทธ๊ฒƒ์„ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋นˆ ๋ฐฐ์—ด([])์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด effect๋Š” React์—๊ฒŒ props๋‚˜ state์—์„œ ๊ฐ€์ ธ์˜จ ์–ด๋–ค ๊ฐ’์—๋„ ์˜์กดํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋‹ค์‹œ ์‹คํ–‰ํ•  ํ•„์š”๊ฐ€ ์ „ํ˜€ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋กœ ๊ฐ„์ฃผํ•˜์ง€๋Š” ์•Š๊ณ , ์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์ด ํ•ญ์ƒ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์ง์ ‘์ ์œผ๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค.

๋นˆ ๋ฐฐ์—ด([])์„ ์ „๋‹ฌํ•œ๋‹ค๋ฉด effect ์•ˆ์— ์žˆ๋Š” props์™€ state๋Š” ํ•ญ์ƒ ์ดˆ๊นƒ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ์จ []์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์นœ์ˆ™ํ•œ componentDidMount์™€ componentWillUnmount์— ์˜ํ•œ ๊ฐœ๋…๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋Š๊ปด์ง€๊ฒ ์ง€๋งŒ, effect๊ฐ€ ๋„ˆ๋ฌด ์ž์ฃผ ๋ฆฌ๋ Œ๋”๋ง ๋˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•œ ๋ณดํ†ต ๋” ๋‚˜์€ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ชจ๋‘ ๊ทธ๋ ค์งˆ ๋•Œ๊นŒ์ง€ React๋Š” useEffect์˜ ์ˆ˜ํ–‰์„ ์ง€์—ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์ž‘์—…์˜ ์ˆ˜ํ–‰์ด ๋ฌธ์ œ๊ฐ€ ๋˜์ง€๋Š” ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.

eslint-plugin-react-hooks ํŒจํ‚ค์ง€์˜ exhaustive-deps ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์˜์กด์„ฑ์ด ๋ฐ”๋ฅด์ง€ ์•Š๊ฒŒ ์ •์˜๋˜์—ˆ๋‹ค๋ฉด ๊ทธ์— ๋Œ€ํ•ด ๊ฒฝ๊ณ ํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์€ effect ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ ๊ฐœ๋…์ ์œผ๋กœ๋Š”, ์ด ๊ธฐ๋ฒ•์€ effect ํ•จ์ˆ˜๊ฐ€ ๋ฌด์—‡์ผ์ง€๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. effect ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ฐธ์กฐ๋˜๋Š” ๋ชจ๋“  ๊ฐ’์€ ์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์— ๋“œ๋Ÿฌ๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์—๋Š” ์ถฉ๋ถ„ํžˆ ๋ฐœ์ „๋œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ด ๋ฐฐ์—ด์„ ์ž๋™์ ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

useContext

const value = useContext(MyContext);

context ๊ฐ์ฒด(React.createContext์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ’)์„ ๋ฐ›์•„ ๊ทธ context์˜ ํ˜„์žฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. context์˜ ํ˜„์žฌ ๊ฐ’์€ ํŠธ๋ฆฌ ์•ˆ์—์„œ ์ด Hook์„ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์ด์— ์žˆ๋Š” <MyContext.Provider>์˜ value prop์— ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด <MyContext.Provider>๊ฐ€ ๊ฐฑ์‹ ๋˜๋ฉด ์ด Hook์€ ๊ทธ MyContext provider์—๊ฒŒ ์ „๋‹ฌ๋œ ๊ฐ€์žฅ ์ตœ์‹ ์˜ context value๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ Œ๋”๋Ÿฌ๋ฅผ ํŠธ๋ฆฌ๊ฑฐ ํ•ฉ๋‹ˆ๋‹ค. ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ React.memo ๋˜๋Š” shouldComponentUpdate๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ useContext๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ ์ž์ฒด์—์„œ๋ถ€ํ„ฐ ๋‹ค์‹œ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค.

useContext๋กœ ์ „๋‹ฌํ•œ ์ธ์ž๋Š” context ๊ฐ์ฒด ๊ทธ ์ž์ฒด์ด์–ด์•ผ ํ•จ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.

  • ๋งž๋Š” ์‚ฌ์šฉ: useContext(MyContext)
  • ํ‹€๋ฆฐ ์‚ฌ์šฉ: useContext(MyContext.Consumer)
  • ํ‹€๋ฆฐ ์‚ฌ์šฉ: useContext(MyContext.Provider)

useContext๋ฅผ ํ˜ธ์ถœํ•œ ์ปดํฌ๋„ŒํŠธ๋Š” context ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ญ์ƒ ๋ฆฌ๋ Œ๋”๋ง ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋ง ํ•˜๋Š” ๊ฒƒ์— ๋น„์šฉ์ด ๋งŽ์ด ๋“ ๋‹ค๋ฉด, ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒ

์—ฌ๋Ÿฌ๋ถ„์ด Hook ๋ณด๋‹ค context API์— ์นœ์ˆ™ํ•˜๋‹ค๋ฉด useContext(MyContext)๋Š” ํด๋ž˜์Šค์—์„œ์˜ static contextType = MyContext ๋˜๋Š” <MyContext.Consumer>์™€ ๊ฐ™๋‹ค๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

useContext(MyContext)๋Š” context๋ฅผ ์ฝ๊ณ  context์˜ ๋ณ€๊ฒฝ์„ ๊ตฌ๋…ํ•˜๋Š” ๊ฒƒ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. context์˜ ๊ฐ’์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์—ฌ์ „ํžˆ ํŠธ๋ฆฌ์˜ ์œ— ๊ณ„์ธต์—์„œ์˜ <MyContext.Provider>๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

useContext๋ฅผ Context.Provider์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);  return (    <button style={{ background: theme.background, color: theme.foreground }}>      I am styled by theme context!    </button>  );
}

ํ•ด๋‹น ์˜ˆ์‹œ๋Š” Context ๊ณ ๊ธ‰ ์•ˆ๋‚ด์„œ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ์˜ˆ์‹œ๊ฐ€ hook์œผ๋กœ ์ˆ˜์ •๋˜์—ˆ์œผ๋ฉฐ ์•ˆ๋‚ด์„œ์—์„œ Context๋ฅผ ์–ธ์ œ, ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์ž์„ธํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ Hook

๋‹ค์Œ์˜ Hook๋Š” ์ด์ „ ์„น์…˜์—์„œ์˜ ๊ธฐ๋ณธ Hook์˜ ๋ณ€๊ฒฝ์ด๊ฑฐ๋‚˜ ํŠน์ •ํ•œ ๊ฒฝ์šฐ์—๋งŒ ํ•„์š”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ตํžˆ๋Š” ๊ฒƒ์— ๋„ˆ๋ฌด ์••๋ฐ•๋ฐ›์ง€๋Š” ๋งˆ์„ธ์š”.

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

useState์˜ ๋Œ€์ฒด ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. (state, action) => newState์˜ ํ˜•ํƒœ๋กœ reducer๋ฅผ ๋ฐ›๊ณ  dispatch ๋ฉ”์„œ๋“œ์™€ ์ง์˜ ํ˜•ํƒœ๋กœ ํ˜„์žฌ state๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. (Redux์— ์ต์ˆ™ํ•˜๋‹ค๋ฉด ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์—ฌ๋Ÿฌ๋ถ„์€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.)

๋‹ค์ˆ˜์˜ ํ•˜์œ—๊ฐ’์„ ํฌํ•จํ•˜๋Š” ๋ณต์žกํ•œ ์ •์  ๋กœ์ง์„ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ๋‚˜ ๋‹ค์Œ state๊ฐ€ ์ด์ „ state์— ์˜์กด์ ์ธ ๊ฒฝ์šฐ์— ๋ณดํ†ต useState๋ณด๋‹ค useReducer๋ฅผ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ useReducer๋Š” ์ž์„ธํ•œ ์—…๋ฐ์ดํŠธ๋ฅผ ํŠธ๋ฆฌ๊ฑฐ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š”๋ฐ, ์ด๊ฒƒ์€ ์ฝœ๋ฐฑ ๋Œ€์‹  dispatch๋ฅผ ์ „๋‹ฌ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” useState ๋‚ด์šฉ์— ์žˆ๋˜ ์นด์šดํ„ฐ ์˜ˆ์‹œ์ธ๋ฐ reducer๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋‹ค์‹œ ์ž‘์„ฑํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

์ฃผ์˜

React๋Š” dispatch ํ•จ์ˆ˜์˜ ๋™์ผ์„ฑ์ด ์•ˆ์ •์ ์ด๊ณ  ๋ฆฌ๋ Œ๋”๋ง ์‹œ์—๋„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฆฌ๋ผ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด useEffect๋‚˜ useCallback ์˜์กด์„ฑ ๋ชฉ๋ก์— ์ด ํ•จ์ˆ˜๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์•„๋„ ๊ดœ์ฐฎ์€ ์ด์œ ์ž…๋‹ˆ๋‹ค.

์ดˆ๊ธฐ state์˜ ๊ตฌ์ฒดํ™”

useReducer state์˜ ์ดˆ๊ธฐํ™”์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์œ ์Šค์ผ€์ด์Šค์— ๋”ฐ๋ผ์„œ ํ•œ ๊ฐ€์ง€๋ฅผ ์„ ํƒํ•˜์„ธ์š”. ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ ์ดˆ๊ธฐ state๋ฅผ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  const [state, dispatch] = useReducer(
    reducer,
    {count: initialCount}  );

์ฃผ์˜

React์—์„œ๋Š” Reducer์˜ ์ธ์ž๋กœ์จ state = initialState์™€ ๊ฐ™์€ ์ดˆ๊ธฐ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š”, Redux์—์„œ๋Š” ๋ณดํŽธํ™”๋œ ๊ด€์Šต์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋•Œ๋•Œ๋กœ ์ดˆ๊ธฐ๊ฐ’์€ props์— ์˜์กดํ•  ํ•„์š”๊ฐ€ ์žˆ์–ด Hook ํ˜ธ์ถœ์—์„œ ์ง€์ •๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด ์ •๋ง ํ•„์š”ํ•˜๋‹ค๋ฉด useReducer(reducer, undefined, reducer)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ Redux๋ฅผ ๋ชจ๋ฐฉํ•  ์ˆ˜๋Š” ์žˆ๊ฒ ์ง€๋งŒ, ์ด ๋ฐฉ๋ฒ•์„ ๊ถŒ์žฅํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

์ดˆ๊ธฐํ™” ์ง€์—ฐ

์ดˆ๊ธฐ state๋ฅผ ์กฐ๊ธˆ ์ง€์—ฐํ•ด์„œ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” init ํ•จ์ˆ˜๋ฅผ ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐ state๋Š” init(initialArg)์— ์„ค์ •๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ reducer ์™ธ๋ถ€์—์„œ ์ดˆ๊ธฐ state๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋กœ์ง์„ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์–ด๋–ค ํ–‰๋™์— ๋Œ€ํ•œ ๋Œ€์‘์œผ๋กœ ๋‚˜์ค‘์— state๋ฅผ ์žฌ์„ค์ •ํ•˜๋Š” ๋ฐ์—๋„ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

function init(initialCount) {  return {count: initialCount};}
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    case 'reset':      return init(action.payload);    default:
      throw new Error();
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: initialCount})}>        Reset
      </button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

dispatch์˜ ํšŒํ”ผ

Reducer Hook์—์„œ ํ˜„์žฌ state์™€ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ React๋Š” ์ž์‹์„ ๋ฆฌ๋ Œ๋”๋งํ•˜๊ฑฐ๋‚˜ effect๋ฅผ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ์ด๊ฒƒ๋“ค์„ ํšŒํ”ผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. (React๋Š” Object.is ๋น„๊ต ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.)

์‹คํ–‰์„ ํšŒํ”ผํ•˜๊ธฐ ์ „์— React์—์„œ ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜์„ธ์š”. React๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํŠธ๋ฆฌ์— ๊ทธ ์ด์ƒ์œผ๋กœ ใ€Œ๋” ๊นŠ๊ฒŒใ€ ๊นŒ์ง€๋Š” ๊ฐ€์ง€ ์•Š์„ ๊ฒƒ์ด๋ฏ€๋กœ ํฌ๊ฒŒ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์œผ์…”๋„ ๋ฉ๋‹ˆ๋‹ค. ๋ Œ๋”๋ง ์‹œ์— ๊ณ ๋น„์šฉ์˜ ๊ณ„์‚ฐ์„ ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด useMemo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ๊ฒƒ๋“ค์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ์ฝœ๋ฐฑ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ธ๋ผ์ธ ์ฝœ๋ฐฑ๊ณผ ๊ทธ๊ฒƒ์˜ ์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜์„ธ์š”. useCallback์€ ์ฝœ๋ฐฑ์˜ ๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ๋ฒ„์ „์„ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ๋ฒ„์ „์€ ์ฝœ๋ฐฑ์˜ ์˜์กด์„ฑ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ์—๋งŒ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€, ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด (์˜ˆ๋กœ shouldComponentUpdate๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ) ์ฐธ์กฐ์˜ ๋™์ผ์„ฑ์— ์˜์กด์ ์ธ ์ตœ์ ํ™”๋œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ์ฝœ๋ฐฑ์„ ์ „๋‹ฌํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

useCallback(fn, deps)์€ useMemo(() => fn, deps)์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ฃผ์˜

์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์ด ์ฝœ๋ฐฑ์— ์ธ์ž๋กœ ์ „๋‹ฌ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ ๊ฐœ๋…์ ์œผ๋กœ๋Š”, ์ด ๊ธฐ๋ฒ•์€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋ฌด์—‡์ผ์ง€๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ ์•ˆ์—์„œ ์ฐธ์กฐ๋˜๋Š” ๋ชจ๋“  ๊ฐ’์€ ์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์— ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์—๋Š” ์ถฉ๋ถ„ํžˆ ๋ฐœ์ „๋œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ด ๋ฐฐ์—ด์„ ์ž๋™์ ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

eslint-plugin-react-hooks ํŒจํ‚ค์ง€์˜ ์ผ๋ถ€๋กœ์จ exhaustive-deps ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์˜์กด์„ฑ์ด ๋ฐ”๋ฅด์ง€ ์•Š๊ฒŒ ์ •์˜๋˜์—ˆ๋‹ค๋ฉด ๊ทธ์— ๋Œ€ํ•ด ๊ฒฝ๊ณ ํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

โ€œ์ƒ์„ฑ(create)โ€ ํ•จ์ˆ˜์™€ ๊ทธ๊ฒƒ์˜ ์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜์„ธ์š”. useMemo๋Š” ์˜์กด์„ฑ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ์—๋งŒ ๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ๊ฐ’๋งŒ ๋‹ค์‹œ ๊ณ„์‚ฐ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ตœ์ ํ™”๋Š” ๋ชจ๋“  ๋ Œ๋”๋ง ์‹œ์˜ ๊ณ ๋น„์šฉ ๊ณ„์‚ฐ์„ ๋ฐฉ์ง€ํ•˜๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.

useMemo๋กœ ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๋Š” ๋ Œ๋”๋ง ์ค‘์— ์‹คํ–‰๋œ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. ํ†ต์ƒ์ ์œผ๋กœ ๋ Œ๋”๋ง ์ค‘์—๋Š” ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ์ด ํ•จ์ˆ˜ ๋‚ด์—์„œ ํ•˜์ง€ ๋งˆ์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ(side effects)๋Š” useEffect์—์„œ ํ•˜๋Š” ์ผ์ด์ง€ useMemo์—์„œ ํ•˜๋Š” ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋ฐฐ์—ด์ด ์—†๋Š” ๊ฒฝ์šฐ ๋งค ๋ Œ๋”๋ง ๋•Œ๋งˆ๋‹ค ์ƒˆ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

useMemo๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ์˜๋ฏธ์ƒ์œผ๋กœ ๋ณด์žฅ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋Š” ๋งˆ์„ธ์š”. ๊ฐ€๊นŒ์šด ๋ฏธ๋ž˜์— React์—์„œ๋Š”, ์ด์ „ ๋ฉ”๋ชจ์ด์ œ์ด์…˜๋œ ๊ฐ’๋“ค์˜ ์ผ๋ถ€๋ฅผ โ€œ์žŠ์–ด๋ฒ„๋ฆฌ๊ณ โ€ ๋‹ค์Œ ๋ Œ๋”๋ง ์‹œ์— ๊ทธ๊ฒƒ๋“ค์„ ์žฌ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉํ–ฅ์„ ํƒํ• ์ง€๋„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์˜คํ”„์Šคํฌ๋ฆฐ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๋Š” ๋“ฑ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. useMemo๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๊ทธ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜์„ธ์š”.

์ฃผ์˜

์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์€ ํ•จ์ˆ˜์— ์ธ์ž๋กœ ์ „๋‹ฌ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ ๊ฐœ๋…์ ์œผ๋กœ๋Š”, ์ด ๊ธฐ๋ฒ•์€ ํ•จ์ˆ˜๊ฐ€ ๋ฌด์—‡์ผ์ง€๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ฐธ์กฐ๋˜๋Š” ๋ชจ๋“  ๊ฐ’์€ ์˜์กด์„ฑ ๊ฐ’์˜ ๋ฐฐ์—ด์— ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์—๋Š” ์ถฉ๋ถ„ํžˆ ๋ฐœ์ „๋œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ด ๋ฐฐ์—ด์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

eslint-plugin-react-hooks ํŒจํ‚ค์ง€์˜ ์ผ๋ถ€๋กœ์จ exhaustive-deps ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์˜์กด์„ฑ์ด ๋ฐ”๋ฅด์ง€ ์•Š๊ฒŒ ์ •์˜๋˜์—ˆ๋‹ค๋ฉด ๊ทธ์— ๋Œ€ํ•ด ๊ฒฝ๊ณ ํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

useRef

const refContainer = useRef(initialValue);

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

์ผ๋ฐ˜์ ์ธ ์œ ์Šค์ผ€์ด์Šค๋Š” ์ž์‹์—๊ฒŒ ๋ช…๋ น์ ์œผ๋กœ ์ ‘๊ทผํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

๋ณธ์งˆ์ ์œผ๋กœ useRef๋Š” .current ํ”„๋กœํผํ‹ฐ์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์„ ๋‹ด๊ณ  ์žˆ๋Š” โ€œ์ƒ์žโ€์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ์—ฌ๋Ÿฌ๋ถ„์€ DOM์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ refs์— ์นœ์ˆ™ํ•  ์ง€๋„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. <div ref={myRef} />๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ React๋กœ ref ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๋ฉด, React๋Š” ๋…ธ๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋ณ€๊ฒฝ๋œ DOM ๋…ธ๋“œ์— ๊ทธ๊ฒƒ์˜ .current ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ค์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€๋งŒ, ref ์†์„ฑ๋ณด๋‹ค useRef()๊ฐ€ ๋” ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ํด๋ž˜์Šค์—์„œ ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์œ ์‚ฌํ•œ ์–ด๋–ค ๊ฐ€๋ณ€๊ฐ’์„ ์œ ์ง€ํ•˜๋Š” ๋ฐ์— ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ useRef()๊ฐ€ ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. useRef()์™€ {current: ...} ๊ฐ์ฒด ์ž์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์˜ ์œ ์ผํ•œ ์ฐจ์ด์ ์ด๋ผ๋ฉด useRef๋Š” ๋งค๋ฒˆ ๋ Œ๋”๋ง์„ ํ•  ๋•Œ ๋™์ผํ•œ ref ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

useRef๋Š” ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ๋  ๋•Œ ๊ทธ๊ฒƒ์„ ์•Œ๋ ค์ฃผ์ง€๋Š” ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์œ ๋…ํ•˜์„ธ์š”. .current ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€ํ˜•ํ•˜๋Š” ๊ฒƒ์ด ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐœ์ƒ์‹œํ‚ค์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. React๊ฐ€ DOM ๋…ธ๋“œ์— ref๋ฅผ attachํ•˜๊ฑฐ๋‚˜ detachํ•  ๋•Œ ์–ด๋–ค ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋Œ€์‹  ์ฝœ๋ฐฑ ref๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle์€ ref๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์— ๋…ธ์ถœ๋˜๋Š” ์ธ์Šคํ„ด์Šค ๊ฐ’์„ ์‚ฌ์šฉ์žํ™”(customizes)ํ•ฉ๋‹ˆ๋‹ค. ํ•ญ์ƒ ๊ทธ๋ ‡๋“ฏ์ด, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ref๋ฅผ ์‚ฌ์šฉํ•œ ๋ช…๋ นํ˜• ์ฝ”๋“œ๋Š” ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. useImperativeHandle๋Š” forwardRef์™€ ๋”๋ถˆ์–ด ์‚ฌ์šฉํ•˜์„ธ์š”.

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

์œ„์˜ ์˜ˆ์‹œ์—์„œ <FancyInput ref={inputRef} />๋ฅผ ๋ Œ๋”๋งํ•œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋Š” inputRef.current.focus()๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

useLayoutEffect

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

ํ™”๋ฉด ๊ฐฑ์‹  ์ฐจ๋‹จ์˜ ๋ฐฉ์ง€๊ฐ€ ๊ฐ€๋Šฅํ•  ๋•Œ ํ‘œ์ค€ useEffect๋ฅผ ๋จผ์ € ์‚ฌ์šฉํ•˜์„ธ์š”.

ํŒ

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์ฝ”๋“œ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ์— useLayoutEffect๋Š” componentDidMount๋‚˜ componentDidUpdate์™€ ๋™์ผํ•œ ๋‹จ๊ณ„๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ๋จผ์ € useEffect๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๊ณ  ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ๋‹ค์Œ์œผ๋กœ useLayoutEffect๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ๋ฅผ ๊ถŒํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ ๋ Œ๋”๋ง์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋ชจ๋‘ ๋‹ค์šด๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€๋Š” useLayoutEffect์™€ useEffect ์–ด๋Š ๊ฒƒ๋„ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ useLayoutEffect๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ์— ๋Œ€ํ•ด React๊ฐ€ ๊ฒฝ๊ณ ํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” (์ตœ์ดˆ ๋ Œ๋”๋ง ์‹œ์— ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋ฉด) ๋กœ์ง์„ useEffect๋กœ ์ด๋™ํ•œ๋‹ค๊ฑฐ๋‚˜ (useLayoutEffect๊ฐ€ ์ˆ˜ํ–‰๋  ๋•Œ๊นŒ์ง€ HTML์ด ๊นจ์ ธ ๋ณด์ด๋Š” ๊ฒฝ์šฐ๋Š”) ํด๋ผ์ด์–ธํŠธ ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์ปดํฌ๋„ŒํŠธ ๋…ธ์ถœ์„ ์ง€์—ฐํ•˜๋„๋ก ํ•˜์„ธ์š”.

์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ HTML์—์„œ ๋ ˆ์ด์•„์›ƒ effect๊ฐ€ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐฐ์ œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, showChild && <Child />๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์กฐ๊ฑด์ ์œผ๋กœ ๋ Œ๋”๋ง ํ•˜๊ณ  useEffect(() => { setShowChild(true); }, [])๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋…ธ์ถœ์„ ์ง€์—ฐ์‹œํ‚ค์„ธ์š”. ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๊ฐ€ ์ฃผ์ž…๋˜๊ธฐ ์ „์— ๊นจ์ ธ ๋ณด์ผ ์ˆ˜ ์žˆ๋Š” UI๋Š” ํ‘œํ˜„๋˜์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

useDebugValue

useDebugValue(value)

useDebugValue๋Š” React ๊ฐœ๋ฐœ์ž๋„๊ตฌ์—์„œ ์‚ฌ์šฉ์ž Hook ๋ ˆ์ด๋ธ”์„ ํ‘œ์‹œํ•˜๋Š” ๋ฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, โ€œ๋‚˜๋งŒ์˜ Hook ๋งŒ๋“ค๊ธฐโ€์— ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋Š” useFriendStatus ์‚ฌ์šฉ์ž Hook์— ๋Œ€ํ•ด์„œ ์ƒ๊ฐํ•ด ๋ด…์‹œ๋‹ค.

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  // ...

  // Show a label in DevTools next to this Hook  // e.g. "FriendStatus: Online"  useDebugValue(isOnline ? 'Online' : 'Offline');
  return isOnline;
}

ํŒ

๋ชจ๋“  ์‚ฌ์šฉ์ž Hook์— ๋””๋ฒ„๊ทธ ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋ฅผ ๊ถŒํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‚ฌ์šฉ์ž Hook์ด ๊ณต์œ ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ผ๋ถ€์ผ ๋•Œ ๊ฐ€์žฅ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋””๋ฒ„๊ทธ ๊ฐ’ ํฌ๋งทํŒ… ์ง€์—ฐํ•˜๊ธฐ

๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋””์Šคํ”Œ๋ ˆ์ด ๊ฐ’์„ ํฌ๋งทํŒ…ํ•˜๋Š” ๊ฒƒ์ด ๊ณ ๋น„์šฉ์˜ ์—ฐ์‚ฐ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์‚ฌ์‹ค์ƒ Hook์ด ๊ฐ์ง€๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์ด์œ ๋กœ useDebugValue๋Š” ์˜ต์…˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํฌ๋งทํŒ… ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” Hook๊ฐ€ ๊ฐ์ง€๋˜์—ˆ์„ ๋•Œ๋งŒ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ์จ ๋””๋ฒ„๊ทธ ๊ฐ’์„ ์ „๋‹ฌ๋ฐ›์•„ ํฌ๋งท๋œ ๋…ธ์ถœ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž Hook์€ ๋‹ค์Œ์˜ ํฌ๋งท ํ˜•์‹์„ ์‚ฌ์šฉํ•ด์„œ toDateString ํ•จ์ˆ˜๋ฅผ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

useDebugValue(date, date => date.toDateString());
Is this page useful?Edit this page