React: [ESLint] 'exhaustive-deps' ๋ฆฐํŠธ ๊ทœ์น™์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ

์— ๋งŒ๋“  2019๋…„ 02์›” 21์ผ  ยท  111์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: facebook/react

์ผ๋ฐ˜์ ์ธ ๋‹ต๋ณ€

๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก

๋ช‡ ๊ฐ€์ง€ ์ง€์นจ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์ด ๊ฒŒ์‹œ๋ฌผ์˜ ๋Œ“๊ธ€์„ ๋ถ„์„ํ–ˆ์Šต๋‹ˆ๋‹ค: https://github.com/facebook/react/issues/14920#issuecomment -471070149.

๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก๐Ÿ’ก


์ด๊ฒŒ ๋ญ”๊ฐ€์š”

์ด๊ฒƒ์€ useEffect ์™€ ๊ฐ™์€ Hooks์— ๋Œ€ํ•œ ์ข…์†์„ฑ ๋ชฉ๋ก์„ ํ™•์ธํ•˜๋Š” ์ƒˆ๋กœ์šด ESLint ๊ทœ์น™์œผ๋กœ, ์˜ค๋ž˜๋œ ํด๋กœ์ € ํ•จ์ •์œผ๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ž๋™ ์ˆ˜์ •์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์ฃผ์— ๋” ๋งŽ์€ ๋ฌธ์„œ๋ฅผ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

autofix demo

์„ค์น˜

yarn add eslint-plugin-react-hooks<strong i="18">@next</strong>
# or
npm install eslint-plugin-react-hooks<strong i="19">@next</strong>

ESLint ๊ตฌ์„ฑ:

{
  "plugins": ["react-hooks"],
  // ...
  "rules": {
    "react-hooks/rules-of-hooks": 'error',
    "react-hooks/exhaustive-deps": 'warn' // <--- THIS IS THE NEW RULE
  }
}

๊ทœ์น™์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์‚ฌ๋ก€:

function Foo(props) {
  useEffect(() => {
    console.log(props.name);
  }, []); // <-- should error and offer autofix to [props.name]
}

๋ฆฐํŠธ ๊ทœ์น™์ด ๋ถˆํ‰ํ•˜์ง€๋งŒ ๋‚ด ์ฝ”๋“œ๋Š” ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค!

์ด ์ƒˆ๋กœ์šด react-hooks/exhaustive-deps ๋ฆฐํŠธ ๊ทœ์น™์ด ์‹คํ–‰๋˜์ง€๋งŒ ์ฝ”๋“œ๊ฐ€ ์ •ํ™•ํ•˜๋‹ค๊ณ  ์ƒ๊ฐ ๋˜๋ฉด ์ด ํ˜ธ์— ๊ฒŒ์‹œํ•˜์‹ญ์‹œ์˜ค.


์˜๊ฒฌ์„ ๊ฒŒ์‹œํ•˜๊ธฐ ์ „์—

๋‹ค์Œ ์„ธ ๊ฐ€์ง€๋ฅผ ํฌํ•จ ํ•˜์‹ญ์‹œ์˜ค .

  1. ์—ฌ์ „ํžˆ ์˜๋„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์ตœ์†Œํ•œ์˜ ์ฝ”๋“œ ์˜ˆ์ œ ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” CodeSandbox("foo bar"๊ฐ€ ์•„๋‹ˆ๋ผ ๊ตฌํ˜„ํ•˜๋Š” ์‹ค์ œ UI ํŒจํ„ด ).
  2. ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜ํ–‰ ํ•˜๋Š”
  3. Hook/์ปดํฌ๋„ŒํŠธ์˜ ์˜๋„๋œ API ์— ๋Œ€ํ•œ ์„ค๋ช…์ž…๋‹ˆ๋‹ค.

please

ํ•˜์ง€๋งŒ ์ œ ๊ฒฝ์šฐ๋Š” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒƒ๋“ค์„ ํฌํ•จํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค!

๋‹น์‹ ์—๊ฒŒ๋Š” ๊ฐ„๋‹จํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์šฐ๋ฆฌ์—๊ฒŒ๋Š” ์ „ํ˜€ ๊ฐ„๋‹จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์˜๊ฒฌ์— ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ(์˜ˆ: CodeSandbox ๋งํฌ ์—†์Œ), ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ† ๋ก ์„ ์ถ”์ ํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์—

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

ESLint Rules Discussion

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์šฐ๋ฆฌ๋Š” ์˜ค๋Š˜ @threepointone ์œผ๋กœ

Lint ๊ทœ์น™์—์„œ ์ˆ˜์ •๋จ

๊ด€๋ จ ์—†๋Š” useEffect ์ข…์†์„ฑ

์ด ๊ทœ์น™์€ ํ•ฉ๋ฒ•์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋” ์ด์ƒ "์™ธ๋ถ€" dep๋ฅผ useEffect ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ๊ตฌ์„ฑ ์š”์†Œ์— ์žˆ์ง€๋งŒ ํšจ๊ณผ ์™ธ๋ถ€์—์„œ ์ •์˜๋œ ๊ธฐ๋Šฅ

Linter๋Š” ์ง€๊ธˆ ์•ˆ์ „ํ•œ ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ๊ฒฝ๊ณ ํ•˜์ง€ ์•Š์ง€๋งŒ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ์šฐ์—๋Š” ๋” ๋‚˜์€ ์ œ์•ˆ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ํšจ๊ณผ ๋‚ด์—์„œ ํ•จ์ˆ˜๋ฅผ ์ด๋™ํ•˜๊ฑฐ๋‚˜ useCallback ๋ž˜ํ•‘).

์‚ฌ์šฉ์ž ์ฝ”๋“œ์—์„œ ์ˆ˜์ •ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Œ

props ๋ณ€๊ฒฝ ์‹œ ์ƒํƒœ ์žฌ์„ค์ •

์ด๊ฒƒ์€ ๋” ์ด์ƒ ๋ฆฐํŠธ ์œ„๋ฐ˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์ง€๋งŒ props์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ์ƒํƒœ๋ฅผ ์žฌ์„ค์ •ํ•˜๋Š” ๊ด€์šฉ์  ๋ฐฉ๋ฒ•์€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค . ์ด ์†”๋ฃจ์…˜์—๋Š” ์ผ๊ด€์„ฑ ์—†๋Š” ๋ Œ๋”๋ง์ด ์ถ”๊ฐ€๋กœ ํฌํ•จ๋˜๋ฏ€๋กœ ๋ฐ”๋žŒ์งํ•œ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

"๋‚ด ๋น„ ๊ธฐ๋Šฅ ๊ฐ’์€ ์ผ์ •ํ•ฉ๋‹ˆ๋‹ค"

ํ›„ํฌ๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ์ •ํ™•ํ•จ์„ ์ถ”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์ด (๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ๋Š” ์ƒ๋žต ํ•  ์ˆ˜ ์žˆ์Œ) deps๋ฅผ ์ง€์ •ํ•˜๋ฉด, ์šฐ๋ฆฌ๋Š” ๊ฐ•ํ•˜๊ฒŒ ๋‹น์‹ ์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ์ƒ๊ฐ๋„ ์‚ฌ๋žŒ์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์˜ˆ, ์ด useDebounce ์˜ˆ์—์„œ๋Š” ์ง€์—ฐ์ด ๋ณ€๊ฒฝ ๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—ฌ์ „ํžˆ ๋ฒ„๊ทธ์ด์ง€๋งŒ Hook์€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹ค๋ฅธ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋„ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. (์˜ˆ: Hooks๋Š” ๋ชจ๋“  ๊ฐ’์ด ๋™์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ซ ๋ฆฌ๋กœ๋”ฉ๊ณผ ํ›จ์”ฌ ๋” ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค.)

ํŠน์ • ๊ฐ’์ด ์ •์ ์ด๋ผ๊ณ  ์ ˆ๋Œ€์ ์œผ๋กœ ์ฃผ์žฅํ•œ๋‹ค๋ฉด ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฐ€์žฅ ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์€ API์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

const useFetch = createFetch({ /* config object */});
const useDebounce = createDebounce(500);
const FormInput = createInput({ rules: [emailValidator, phoneValidator] });

๊ทธ๋Ÿฐ ๋‹ค์Œ render ์•ˆ์— ๋„ฃ์ง€ ์•Š๋Š” ํ•œ ๋ถ„๋ช…ํžˆ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (์ด๊ฒƒ์€ Hook์˜ ๊ด€์šฉ์  ์‚ฌ์šฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค.) ํ•˜์ง€๋งŒ <Slider min={50} /> can never change ๋ผ๋Š” ๋ง์€ ์‹ค์ œ๋กœ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ๋ˆ„๊ตฐ๊ฐ€ ๊ทธ๊ฒƒ์„ <Slider min={state ? 50 : 100} /> ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋ˆ„๊ตฐ๊ฐ€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let slider
if (isCelsius) {
  slider = <Slider min={0} max={100} />
} else {
  slider = <Slider min={32} max={212} />
}

๋ˆ„๊ตฐ๊ฐ€ isCelsius ์ƒํƒœ๋ฅผ ์ „ํ™˜ํ•˜๋ฉด min ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ Slider ๊ฐ€ ๋™์ผํ•œ์ง€ ์—ฌ๋ถ€๋Š” ๋ถ„๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ํŠธ๋ฆฌ์—์„œ ๋™์ผํ•œ ์œ„์น˜์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค). ๋”ฐ๋ผ์„œ ์ด๊ฒƒ์€ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ธก๋ฉด์—์„œ ์ค‘์š”ํ•œ ๋ฐœํŒ์ž…๋‹ˆ๋‹ค. React์˜ ์ฃผ์š” ํฌ์ธํŠธ๋Š” ์—…๋ฐ์ดํŠธ๊ฐ€ ์ดˆ๊ธฐ ์ƒํƒœ์ฒ˜๋Ÿผ ๋ Œ๋”๋ง๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋ณดํ†ต ์–ด๋Š ๊ฒƒ์ด ์–ด๋Š ์ƒํƒœ์ธ์ง€ ์•Œ ์ˆ˜ ์—†์Œ). prop ๊ฐ’ B๋ฅผ ๋ Œ๋”๋งํ•˜๋“  prop ๊ฐ’ A์—์„œ B๋กœ ์ด๋™ํ•˜๋“  ์ƒ๊ด€์—†์ด ๋™์ผํ•˜๊ฒŒ ๋ณด์ด๊ณ  ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š์ง€๋งŒ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ์ ์šฉ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ ๊ฒฝ๊ณ ํ•˜๋Š”(๊ทธ๋Ÿฌ๋‚˜ ์ฒซ ๋ฒˆ์งธ ๊ฐ’์„ ์ œ๊ณตํ•˜๋Š”) ํ›„ํฌ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์–ด๋„ ๊ทธ๋•Œ๋Š” ์ฃผ๋ชฉ๋ฐ›์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋” ํฝ๋‹ˆ๋‹ค.

function useMyHook(a) {
  const initialA = usePossiblyStaleValue(a);
  // ...
}

function usePossiblyStaleValue(value) {
  const ref = useRef(value);

  if (process.env.NODE_ENV !== 'production') {
    if (ref.current !== value) { // Or your custom comparison logic
      console.error(
        'Unlike normally in React, it is not supported ' +
        'to pass dynamic values to useMyHook(). Sorry!'
      );
    }
  }

  return ref.current;
}

์—…๋ฐ์ดํŠธ๋ฅผ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์—†๋Š” ํ•ฉ๋ฒ•์ ์ธ ๊ฒฝ์šฐ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด jQuery ํ”Œ๋Ÿฌ๊ทธ์ธ์ด๋‚˜ DOM API์™€ ๊ฐ™์ด ํ•˜์œ„ ์ˆ˜์ค€ API๊ฐ€ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์†Œ๋น„์ž๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฒฝ๊ณ ๊ฐ€ ์—ฌ์ „ํžˆ ์ ์ ˆํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์—…๋ฐ์ดํŠธ์—์„œ key ๋ฅผ ์žฌ์„ค์ •ํ•˜๋Š” ๋ž˜ํผ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šฌ๋ผ์ด๋”๋‚˜ ์ฒดํฌ๋ฐ•์Šค์™€ ๊ฐ™์€ ๋ฆฌํ”„ ๊ตฌ์„ฑ์š”์†Œ์— ๋” ์ ํ•ฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

"๋‚ด ๊ธฐ๋Šฅ ๊ฐ’์€ ์ผ์ •ํ•ฉ๋‹ˆ๋‹ค"

์šฐ์„ , ๊ทธ๊ฒƒ์ด ์ผ์ •ํ•˜๊ณ  ์ตœ์ƒ์œ„ ๋ฒ”์œ„๋กœ ํ˜ธ์ด์ŠคํŠธ๋˜๋ฉด ๋ฆฐํ„ฐ๋Š” ๋ถˆํ‰ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์€ ์†Œํ’ˆ์ด๋‚˜ ์ปจํ…์ŠคํŠธ์—์„œ ์˜ค๋Š” ๊ฒƒ์—๋Š” ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ์ง„์ • ์œผ๋กœ ์ผ์ •ํ•˜๋‹ค๋ฉด deps๋กœ ์ง€์ •ํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ Hook ๋‚ด๋ถ€์˜ setState ํ•จ์ˆ˜๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ฐ˜ํ™˜๋œ ๋‹ค์Œ ํšจ๊ณผ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์ด. Lint ๊ทœ์น™์€ ์ด์™€ ๊ฐ™์€ ๊ฐ„์ ‘ ์ฐธ์กฐ๋ฅผ ์ดํ•ดํ•  ๋งŒํผ ๋˜‘๋˜‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ํ•œํŽธ์œผ๋กœ ๋ˆ„๊ตฌ๋“ ์ง€ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์— ๋‚˜์ค‘์— ํ•ด๋‹น ์ฝœ๋ฐฑ์„ ๋ž˜ํ•‘ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ทธ ์•ˆ์— ์žˆ๋Š” ๋‹ค๋ฅธ prop ๋˜๋Š” state๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ผ์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค! ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋ฉด ๋ถˆ์พŒํ•œ prop/state ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค.

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

์ด๊ฒƒ์˜ ๋ฐ˜๋Œ€ ์ŠคํŽ™ํŠธ๋Ÿผ์—๋Š” ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(ํ•จ์ˆ˜ ๊ฐ’์€ ํ•ญ์ƒ ๋ณ€๊ฒฝ๋จ). ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ(๋™์ผํ•œ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ) ์ด์ œ Lint ๊ทœ์น™์—์„œ ์ด๋ฅผ ํฌ์ฐฉํ•˜๊ณ  ์ˆ˜์ • ์‚ฌํ•ญ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ช‡ ๋‹จ๊ณ„ ์•„๋ž˜๋กœ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ†ต๊ณผํ•˜๋ฉด ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค.

์—ฌ์ „ํžˆ useCallback ๋กœ ๊ฐ์‹ธ์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์  ์œผ๋กœ ํ•จ์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์€ ์œ ํšจํ•˜๋ฉฐ ๋ฒ„๊ทธ์˜ ์œ„ํ—˜ ์—†์ด ์ด ๊ฒฝ์šฐ๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. onChange={shouldHandle ? handleChange : null} ๋˜๋Š” ๊ฐ™์€ ์œ„์น˜์—์„œ foo ? <Page fetch={fetchComments /> : <Page fetch={fetchArticles /> ๋ Œ๋”๋ง ๋“ฑ. ๋˜๋Š” ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ ์ƒํƒœ๋ฅผ ๋‹ซ๋Š” fetchComments ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ž‘์ด ์ž๋™์œผ๋กœ ๋ณ€๊ฒฝ๋˜์ง€๋งŒ ํ•จ์ˆ˜ ์ฐธ์กฐ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž๋…€๋Š” ํ•ด๋‹น ์—…๋ฐ์ดํŠธ๋ฅผ ๋†“์น  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž๋…€์—๊ฒŒ ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ ์™ธ์—๋Š” ์˜ต์…˜์ด ์—†์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ useCallback ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ID ์ž์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Š” ์œ ์šฉํ•œ ์†์„ฑ์ด๋ฉฐ ํ”ผํ•ด์•ผ ํ•  ์žฅ์• ๋ฌผ์ด ์•„๋‹™๋‹ˆ๋‹ค.

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

useWarnAboutTooFrequentChanges([deps]);

์ด๊ฒƒ์€ ์ด์ƒ์ ์ด์ง€ ์•Š์œผ๋ฉฐ ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ ๋” ์šฐ์•„ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ข‹์•„ํ•˜๋Š” ๊ฒฝ์šฐ ๋™์˜ ์ด ๊ฝค ๋ถˆ์พŒํ•œ์ž…๋‹ˆ๋‹ค. ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์€ rules ์ •์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜ˆ: API๋ฅผ createTextInput(rules) ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  register ๋ฐ unregister ์„ useCallback . ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์€ register ๋ฐ unregister ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  dispatch ๋งŒ ๋„ฃ๋Š” ๋ณ„๋„์˜ ์ปจํ…์ŠคํŠธ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ฝ๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ ID๋ฅผ ๊ฐ–์ง€ ์•Š์„ ๊ฒƒ์ž„์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

ํ•จ์ˆ˜ ์ข…์†์„ฑ์„ ์™„์ „ํžˆ ๋ฌด์‹œํ•˜๋ฉด ํ•จ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ Hooks์—์„œ ๋” ๋‚˜์œ ๋ฒ„๊ทธ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ณ„์† ์˜ค๋ž˜๋œ props์™€ state๊ฐ€ ํ‘œ์‹œ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๋ณตํ•ฉ ๊ฐ€์น˜ ๋ณ€ํ™”์— ๋Œ€์‘ํ•˜๊ธฐ

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

์ฆ‰, fullName ๋ฅผ setSubmittedData({firstName, lastName}) ๋Œ€์‹  [submittedData] ๋กœ ๋งŒ๋“ค๊ณ  firstName ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ข…์†์„ฑ์„ ํ†ตํ•ด ์‹œ๋„ํ•œ ์ž‘์—…์„ ๊ณ„์† ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค lastName .

ํ•„์ˆ˜/๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์™€ ํ†ตํ•ฉ

jQuery ํ”Œ๋Ÿฌ๊ทธ์ธ ๋˜๋Š” ์›์‹œ DOM API์™€ ๊ฐ™์€ ํ•„์ˆ˜ ํ•ญ๋ชฉ๊ณผ ํ†ตํ•ฉํ•  ๋•Œ ์•ฝ๊ฐ„์˜ ๋ถˆํŽธํ•จ์ด ์˜ˆ์ƒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ์˜ˆ์ œ์—์„œ ํšจ๊ณผ ๋ฅผ ์ข€ ๋” ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.


์•„๋ฌด๋„ ์žŠ์ง€ ์•Š์•˜์œผ๋ฉด ์ข‹๊ฒ ์–ด! ๋‚ด๊ฐ€ ํ•œ ๊ฒฝ์šฐ ๋˜๋Š” ๋ญ”๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ์šฐ๋ฆฌ๋Š” ๊ณง ์ด๊ฒƒ์˜ ๊ตํ›ˆ์„ ์ผ๋ถ€ ๋ฌธ์„œ๋กœ ๋ฐ”๊พธ๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  111 ๋Œ“๊ธ€

์ด ์˜ˆ์—๋Š” ๋‹ต์žฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/facebook/react/issues/14920#issuecomment -466145690

์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค

์ด๊ฒƒ์€ defaultIndeterminate ์†Œํ’ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๊ธฐ ๋ Œ๋”๋ง์—์„œ ๋ถˆํ™•์‹คํ•œ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ์ œ์–ด๋˜์ง€ ์•Š๋Š” Checkbox ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค( indeterminate ์š”์†Œ ์†์„ฑ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ref๋ฅผ ์‚ฌ์šฉํ•˜๋Š” JS์—์„œ๋งŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ). ์ด ์†Œํ’ˆ์€ defaultValue ์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜๋„๋ก ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์—ฌ๊ธฐ์„œ ํ•ด๋‹น ๊ฐ’์€ ์ดˆ๊ธฐ ๋ Œ๋”๋ง์—์„œ๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๊ทœ์น™์€ defaultIndeterminate ๊ฐ€ ์ข…์†์„ฑ ๋ฐฐ์—ด์—์„œ ๋ˆ„๋ฝ๋˜์—ˆ๋‹ค๊ณ  ๋ถˆํ‰ํ•˜์ง€๋งŒ ์ด๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์ƒˆ ๊ฐ’์ด ์ „๋‹ฌ๋˜๋Š” ๊ฒฝ์šฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ œ์–ด๋˜์ง€ ์•Š์€ ์ƒํƒœ๋ฅผ ์ž˜๋ชป ๋ฎ์–ด์“ฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ข…์†์„ฑ ๋ฐฐ์—ด์€ prop์— ์˜ํ•ด ์™„์ „ํžˆ ์ œ์–ด๋˜์ง€ ์•Š๋Š” ์ƒํƒœ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์™„์ „ํžˆ ์ œ๊ฑฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

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

์žฌ: https://github.com/facebook/react/issues/14920#issuecomment -466144466

@billyjanitsch ๋Œ€์‹  ์ž‘๋™ํ• ๊นŒ์š”? https://codesandbox.io/s/jpx1pmy7ry

defaultIndeterminate ์ดˆ๊ธฐํ™”๋˜๋Š” indeterminate ์— useState ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํšจ๊ณผ๋Š” [indeterminate] ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„๋“ค์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์ง€๋งŒ ๋‚˜์ค‘์— ๋ณ€๊ฒฝํ•˜๋ฉด ํšจ๊ณผ๊ฐ€ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๊นŒ? ๋”ฐ๋ผ์„œ ์ฝ”๋“œ๋Š” ๋ฏธ๋ž˜์˜ ๊ฐ€๋Šฅํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์กฐ๊ธˆ ๋” ์ž˜ ์˜ˆ์ธกํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‚˜๋Š” ์ผ๋ถ€ html์„ ์ „๋‹ฌํ•˜๊ณ  ๊ทธ๊ฒƒ์„ dangerouslySetInnerHtml ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ(์ผ๋ถ€ ํŽธ์ง‘ ๋‚ด์šฉ)๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ (๊ฐ€์žฅ์ž๋ฆฌ?) ์‚ฌ๋ก€๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.
html ์†Œํ’ˆ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ref.current.querySelectorAll ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ๋ฒ•์„ ๊ฑธ ์ˆ˜ ์žˆ๋Š” ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์ด์ œ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ useEffect ์ข…์†์„ฑ์— html ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๊ทœ์น™์„ ๋น„ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•˜๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๊นŒ?

์•„์ด๋””์–ด๋Š” ํŽธ์ง‘ ์ฝ˜ํ…์ธ ์—์„œ ๋ชจ๋“  ๋งํฌ ํด๋ฆญ์„ ๊ฐ€๋กœ์ฑ„๊ณ  ์ผ๋ถ€ ๋ถ„์„์„ ์ถ”์ ํ•˜๊ฑฐ๋‚˜ ๊ธฐํƒ€ ๊ด€๋ จ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์‹ค์ œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ถ•์†Œ๋œ ์˜ˆ์ž…๋‹ˆ๋‹ค.
https://codesandbox.io/s/8njp0pm8v2

react-redux๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ mapDispatchToProps ์—์„œ props์˜ action Creator๋ฅผ ์ „๋‹ฌํ•˜๊ณ  hook์—์„œ ํ•ด๋‹น action Creator๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด exhaustive-deps ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‹น์—ฐํžˆ ์ข…์†์„ฑ ๋ฐฐ์—ด์— redux ์•ก์…˜์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, redux ์•ก์…˜์€ ํ•จ์ˆ˜์ด๊ณ  ์ ˆ๋Œ€ ๋ฐ”๋€Œ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

const onSubmit = React.useCallback(
  () => {
    props.onSubmit(emails);
  },
  [emails, props]
);

๋ฆฐํŠธ๊ฐ€ deps ๋ฅผ [emails, props.onSubmit] ๋กœ ์ˆ˜์ •ํ•˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ ํ•ญ์ƒ deps ๋ฅผ [emails, props] ๋กœ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

  1. ์—ฌ์ „ํžˆ ์˜๋„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์ตœ์†Œํ•œ์˜ ์ฝ”๋“œ ์˜ˆ์ œ ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” CodeSandbox("foo bar"๊ฐ€ ์•„๋‹ˆ๋ผ ๊ตฌํ˜„ํ•˜๋Š” ์‹ค์ œ UI ํŒจํ„ด ).

https://codesandbox.io/s/xpr69pllmz

  1. ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜ํ–‰ ํ•˜๋Š”

์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฉ”์ผ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ํ•ด๋‹น ์ด๋ฉ”์ผ์„ ์•ฑ์— ์ดˆ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ๋ฌธ์ œ์™€ ๊ด€๋ จ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์˜๋„์ ์œผ๋กœ ๋‚˜๋จธ์ง€ UI๋ฅผ button ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.

  1. Hook/์ปดํฌ๋„ŒํŠธ์˜ ์˜๋„๋œ API ์— ๋Œ€ํ•œ ์„ค๋ช…์ž…๋‹ˆ๋‹ค.

๋‚ด ๊ตฌ์„ฑ ์š”์†Œ์—๋Š” onSubmit: (emails: string[]) => void ๋‹จ์ผ ์†Œํ’ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์–‘์‹์„ ์ œ์ถœํ•  ๋•Œ emails ์ƒํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.


ํŽธ์ง‘: https://github.com/facebook/react/issues/14920#issuecomment -467494468์—์„œ ๋‹ต๋ณ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๊ธฐ์ˆ ์ ์œผ๋กœ props.foo() ๊ฐ€ props ์ž์ฒด๋ฅผ this ๋กœ foo ํ˜ธ์ถœ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ foo ๋Š” ์•”์‹œ์ ์œผ๋กœ props ์— ์ข…์†๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ์—๋Š” ๋” ๋‚˜์€ ๋ฉ”์‹œ์ง€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ํ•ญ์ƒ ๊ตฌ์กฐ๋ฅผ ๋ถ„ํ•ดํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค

ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ฉํ•  ๋•Œ ํƒ‘์žฌ ๋ฐ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋šœ๋ ทํ•˜๊ฒŒ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์€ ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ Œ๋”์—์„œ ์ธ์Šคํ„ด์Šค๊ฐ€ ํŒŒ๊ดด๋˜์–ด์„œ๋Š” ์•ˆ ๋˜๋ฏ€๋กœ ์—…๋ฐ์ดํŠธ ํšจ๊ณผ๋ฅผ ๋งˆ์šดํŠธ์— ํฌํ•จํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(๋ฐฐ์—ด์„ ์™„์ „ํžˆ ์ œ๊ฑฐ).

์•ˆ๋…•ํ•˜์„ธ์š”,

์—ฌ๊ธฐ ๋‚ด ์ฝ”๋“œ์— ๋ฌด์—‡์ด ๋ฌธ์ œ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

const [client, setClient] = useState(0);

useEffect(() => {
    getClient().then(client => setClient(client));
  }, ['client']);

React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked ๋ฐ›์•˜์–ด์š”

@joelmoss @sylvainbaronnet ๊ท€ํ•˜์˜ ์˜๊ฒฌ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฌธ์ œ์˜ ๋งจ ์œ„์— ์š”์ฒญํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ท€ํ•˜์˜ ์˜๊ฒฌ์„ ์ˆจ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์ด ํ† ๋ก ์„ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋‹ค์‹œ ๊ฒŒ์‹œํ•˜๊ณ  ๋ชจ๋“  ๊ด€๋ จ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋ฉด ๋Œ€ํ™”๋ฅผ ๊ณ„์†ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค(๋งจ ์œ„ ๊ฒŒ์‹œ๋ฌผ ์ฐธ์กฐ). ์–‘ํ•ด ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

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

์ฝ”๋“œ๊ฐ€ ์žˆ๋Š” ๊ทธ๋Œ€๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. setLastName ๊ฐ€ ๋ฐฐ์—ด์— ํฌํ•จ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  35ํ–‰์—์„œ ๋ฐ”๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๋ฌด์—‡์„ ํ•  ์ƒ๊ฐ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚ด๊ฐ€ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ผ์„ ํ•˜๊ณ  ์žˆ๋Š” ๊ฑธ๊นŒ?

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

์—ฌ์ „ํžˆ ๋” ๋งŽ์€ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ๊ณ ๋งˆ์›Œ

@joelmoss ๋‚ด

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

@gaearon ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋‚ด๊ฐ€ ๋‹ฌ์„ฑํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ

ํšจ๊ณผ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ํ•œ ๋ฒˆ๋งŒ(๋งˆ์šดํŠธ ๋ฐ ๋งˆ์šดํŠธ ํ•ด์ œ ์‹œ) ์ •๋ฆฌํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋นˆ ๋ฐฐ์—ด([])์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŽ์€ ์„ค๋ช… ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. (๊ทธ๋ฆฌ๊ณ  ์ฃผ์ œ๋ฅผ ๋ฒ—์–ด๋‚˜์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค)

๋‹ค์Œ์€ ๋‚ด๊ฐ€ ๊ตฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค. ๋ณ„๊ฑฐ ์•„๋‹Œ ๊ฒƒ ๊ฐ™์ง€๋งŒ ํŒจํ„ด์ด ์‹ค์ œ ์ฝ”๋“œ์™€ 100% ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

https://codesandbox.io/s/2x4q9rzwmp?fontsize=14

  • ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜ํ–‰ ํ•˜๋Š”

์ด ์˜ˆ์—์„œ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค! ๋ฆฐํ„ฐ ๋ฌธ์ œ๋ฅผ ์ œ์™ธํ•˜๊ณ .

  • Hook/์ปดํฌ๋„ŒํŠธ์˜ ์˜๋„๋œ API ์— ๋Œ€ํ•œ ์„ค๋ช…์ž…๋‹ˆ๋‹ค.

ํšจ๊ณผ์—์„œ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋Š” ์ด์™€ ๊ฐ™์€ ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํŠน์ • ์กฐ๊ฑด์ด ์ถฉ์กฑ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ์‹œ๋ฆฌ์ฆˆ ID ๋ณ€๊ฒฝ). ๋ฐฐ์—ด์— ํ•จ์ˆ˜๋ฅผ ํฌํ•จํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ƒŒ๋“œ๋ฐ•์Šค ์ฝ”๋“œ์—์„œ ์‹คํ–‰ํ•  ๋•Œ ๋ฆฐํ„ฐ์—์„œ ์–ป์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

25:5   warning  React Hook useEffect has a missing dependency: 'fetchPodcastsFn'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

๋‚ด ์งˆ๋ฌธ์€ ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ(linter ๊ทœ์น™ ๋˜๋Š” ํ›„ํฌ ๋ฐฐ์—ด ๊ทœ์น™)? ์ด ํšจ๊ณผ๋ฅผ ๋” ๊ด€์šฉ์ ์œผ๋กœ ์„ค๋ช…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@svenanders , fetchPodcastsFn ๋ฅผ ํฌํ•จํ•˜๊ณ  ์‹ถ์ง€ ์•Š์€ ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค ๋ณ€๊ฒฝ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ๋ฉ”๋ชจํ™”ํ•˜๊ฑฐ๋‚˜ ์ •์ ์œผ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ).

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

https://codesandbox.io/s/4xym4yn9kx

  • ๋‹จ๊ณ„

์‚ฌ์šฉ์ž๋Š” ํŽ˜์ด์ง€์˜ ๊ฒฝ๋กœ์— ์•ก์„ธ์Šคํ•˜์ง€๋งŒ ์Šˆํผ ์‚ฌ์šฉ์ž๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ํŽ˜์ด์ง€์—์„œ ๋‹ค๋ฅธ ๊ณณ์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. props.navigate ๋Š” ๋ผ์šฐํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ฃผ์ž…๋˜๋ฏ€๋กœ ์‹ค์ œ๋กœ ํŽ˜์ด์ง€ ๋‹ค์‹œ ๋กœ๋“œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด window.location.assign ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค!

  • ์˜๋„๋œ API

๋‚˜๋Š” ์ฝ”๋“œ ์ƒŒ๋“œ ๋ฐ•์Šค๋กœ ์ œ๋Œ€๋กœ ์˜์กด์„ฑ์— ๋„ฃ์–ดํ•˜์ง€๋งŒ ๋ฆฐํ„ฐ ์ข…์†์„ฑ ๋ชฉ๋ก์ด ์žˆ์–ด์•ผํ•œ๋‹ค๊ณ  ๋‚˜์—๊ฒŒ ๋งํ•˜๊ณ  props ๋Œ€์‹  props.navigate . ์™œ ๊ทธ๋Ÿฐ ๊ฒ๋‹ˆ๊นŒ?

์Šคํฌ๋ฆฐ์ƒท์ด ์žˆ๋Š” ํŠธ์œ—! https://twitter.com/ferdaber/status/1098966716187582464

ํŽธ์ง‘: ์ด๊ฒƒ์ด ๋ฒ„๊ทธ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ํ•œ ๊ฐ€์ง€ ์œ ํšจํ•œ ์ด์œ ๋Š” navigate() ๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ this ์— ์˜์กดํ•˜๋Š” ๋ฉ”์„œ๋“œ์ธ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ธฐ์ˆ ์ ์œผ๋กœ props ๋‚ด๋ถ€์˜ ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋‚ด๋ถ€์˜ ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค this ๋„ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค: https://codesandbox.io/s/711r1zmq50

์˜๋„ํ•œ API:

์ด ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋น ๋ฅด๊ฒŒ ๋ณ€ํ™”ํ•˜๋Š” ๊ฐ’์„ ๋””๋ฐ”์šด์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. debounced ๊ฐ’์€ useDbounce ํ›„ํฌ๊ฐ€ ์ง€์ •๋œ ์‹œ๊ฐ„ ๋™์•ˆ ํ˜ธ์ถœ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ์ตœ์‹  ๊ฐ’์„ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ๋ ˆ์‹œํ”ผ์—์„œ์™€ ๊ฐ™์ด useEffect์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด API ํ˜ธ์ถœ๊ณผ ๊ฐ™์€ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ž‘์—…์ด ๋„ˆ๋ฌด ์ž์ฃผ ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก ์‰ฝ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ๊ณ„:

์ด ์˜ˆ์—์„œ๋Š” Marvel Comic API๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  useDebounce๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ํ‚ค ์ž…๋ ฅ์—์„œ API ํ˜ธ์ถœ์ด ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ข…์†์„ฑ ๋ฐฐ์—ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” "๋ชจ๋“  ๊ฒƒ"์„ ์ถ”๊ฐ€ํ•˜๋Š” IMO๋Š” ํšจ์œจ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด useDebounce Hook ์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค. ์‹ค์ œ ์‚ฌ์šฉ์—์„œ(์ ์–ด๋„ ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ) delay ๋Š” ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง ํ›„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์ง€๋งŒ ๋ชจ๋“  ์žฌ๋ Œ๋”๋ง์—์„œ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ,์ด ํ›„ํฌ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜ useEffect ์ž…๋‹ˆ๋‹ค ๋” ๋‚˜์€๊ฐ€๋˜๊ฒŒํ•ฉ๋‹ˆ๋‹ค [value] ๋Œ€์‹  [value, delay] .

์–•์€ ํ‰๋“ฑ ๊ฒ€์‚ฌ๊ฐ€ ๋งค์šฐ ์ €๋ ดํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์ „๋žต์ ์œผ๋กœ ๋ฐฐ์น˜ํ•˜๋ฉด ์•ฑ์— ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ชจ๋“  ๋‹จ์ผ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ์•ฑ์„ ๋Š๋ฆฌ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ˆ์ถฉ์•ˆ.

์ข…์†์„ฑ ๋ฐฐ์—ด์— ๋ชจ๋“  ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ชจ๋“  ๊ณณ์—์„œ ์ˆœ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ(๋˜๋Š” ๋” ๋‚˜์œ) ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ’ โ€‹โ€‹์ค‘ ์ผ๋ถ€๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ๋Š” ๋งŽ์€ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ @gaearon์ด ๋งํ–ˆ๋“ฏ์ด ์–•์€ ํ‰๋“ฑ ๊ฒ€์‚ฌ๊ฐ€ ๋งค์šฐ ์ €๋ ดํ•˜์ง€ ์•Š๊ณ  ์•ฑ์„ ๋Š๋ฆฌ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๊ทœ์น™์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž ์ง€์ • ํ›„ํฌ์—์„œ ์ž๋™์œผ๋กœ ์ž‘๋™ํ•˜๋„๋ก ์ด ๊ทœ์น™์„ ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ํ”ผ๋“œ๋ฐฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์†Œ์Šค ์ฝ”๋“œ์—์„œ ์‚ฌ๋žŒ๋“ค์ด ์ •๊ทœ์‹์„ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ๋ฅผ ์ด๋ฆ„์œผ๋กœ ์บก์ฒ˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ ค๋Š” ์˜๋„๊ฐ€ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://github.com/facebook/react/blob/ba708fa79b3db6481b7886f9fdb6bb776d0c2fb9/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js#L490 -L492

React ํŒ€์€ ์˜์กด์„ฑ ๋ฐฐ์—ด์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๋ช…๋ช… ๊ทœ์น™์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ• ๊นŒ์š”? ํ›„ํฌ๋Š” ์ด๋ฏธ ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ ํ›„ํฌ๋กœ ๊ฐ์ง€ํ•˜๊ธฐ ์œ„ํ•ด use ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™๋Š” ๊ทœ์น™์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ํŠน์ • ์ข…์†์„ฑ์— ์˜์กดํ•˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ํ›„ํฌ๋ฅผ ๊ฐ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ œ์•ˆํ•˜๋Š” ๊ทœ์น™์€ WithDeps ์™€ ๊ฐ™์€ ์ผ์ข…์˜ ์ ‘๋ฏธ์‚ฌ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ „์ฒด ์‚ฌ์šฉ์ž ์ง€์ • ํ›„ํฌ ์ด๋ฆ„์€ useCustomHookWithDeps ์™€ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. WithDeps ์ ‘๋ฏธ์‚ฌ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์ตœ์ข… ๋ฐฐ์—ด ์ธ์ˆ˜๊ฐ€ ์ข…์†์„ฑ ์ค‘ ํ•˜๋‚˜์ž„์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹regexes๋ฅผ ์ถ”๊ฐ€๋กœ ์ง€์›ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์†Œ๋น„์ž๊ฐ€ ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ •์˜์— ๋Œ€ํ•ด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋ช…์‹œ์ ์œผ๋กœ ๊ตฌ์„ฑํ•˜๋„๋ก ํ•˜๋Š” ๋Œ€์‹  WithDeps ์ ‘๋ฏธ์‚ฌ๊ฐ€ ๋ถ™์€ ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ๋ฅผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž‘์„ฑ์ž๊ฐ€ ๊ฐ„๋‹จํžˆ ๋‚ด๋ณด๋‚ผ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด ํฐ ์ด์ ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ œ3์ž ๋˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ๋™๋“ฑ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๊ฒฝ๊ณ ํ•˜๊ณ  ์ž๋™์œผ๋กœ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

const myEqualityCheck = a => a.includes('@');

useCallback(
  () => {
    // ...
  },
  [myEqualityCheck(a)]
);

useEffect์˜ ๊ฒฝ์šฐ ํ•ด๋‹น "์ข…์†์„ฑ"์ด ํšจ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ๋•Œ๋ฌธ์— "๋ถˆํ•„์š”ํ•œ ์ข…์†์„ฑ" ๊ฒฝ๊ณ ๊ฐ€ ๋‚˜ํƒ€๋‚˜์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ถ€๋ชจ์™€ ์ž์‹์ด๋ผ๋Š” ๋‘ ๊ฐœ์˜ ์นด์šดํ„ฐ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ์นด์šดํ„ฐ๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์ฆ๊ฐ€/๊ฐ์†Œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒ์œ„ ์นด์šดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ํ•˜์œ„ ์นด์šดํ„ฐ๋ฅผ 0์œผ๋กœ ์žฌ์„ค์ •ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„:

  const [parent, setParent] = useState(0);
  const [child, setChild] = useState(0);

  useEffect(
    () => {
      setChild(0);
    },
    [parent] // "unnecessary dependency: 'parent'"
  );

์ฒ ์ €ํ•œ deps ๊ทœ์น™์€ React Hook useEffect has an unnecessary dependency: 'parent'. Either exclude it or remove the dependency array. ๊ฒฝ๊ณ ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

screen shot 2019-02-25 at 11 06 40 am

์•ฑ์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฐํ„ฐ๊ฐ€ ์ด ์ œ์•ˆ์„ ํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

  1. ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค: https://codesandbox.io/s/ol6r9plkv5
  2. ๋‹จ๊ณ„: parent ๋ณ€๊ฒฝ๋˜๋ฉด child ๊ฐ€ 0์œผ๋กœ ์žฌ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
  3. ์˜๋„: ์ข…์†์„ฑ์„ ๋ถˆํ•„์š”ํ•œ ๊ฒƒ์œผ๋กœ ํ”Œ๋ž˜๊ทธ ์ง€์ •ํ•˜๋Š” ๋Œ€์‹  linter๋Š” parent ๊ฐ€ useEffect ์˜ ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์ œ๊ฑฐํ•˜๋„๋ก ์กฐ์–ธํ•˜์ง€ ์•Š์•„์•ผ ํ•จ์„ ์ธ์‹ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

[ํŽธ์ง‘ํ•˜๋‹ค]

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const [parent, setParent] = useState(0)
const [child, setChild] = useState(0)
const previousParent = useRef(parent)

useEffect(() => {
  if (parent !== previousParent.current) {
    setChild(0)
  }

  previousParent.current = parent
}, [parent])

ํ•˜์ง€๋งŒ ๋‚ด๊ฐ€ ์ข‹์•„ํ•˜๋Š” ์›๋ณธ ์Šค๋‹ˆํŽซ์— "์‹œ"๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์„ฑ๋Šฅ ์ตœ์ ํ™”์™€ ์‹ค์ œ ๊ตฌ์„ฑ ์š”์†Œ ๋™์ž‘์„ ์œ„ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ํ•ด์„ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๋‹ฌ๋ ค ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. React Hooks FAQ๋Š” ์„ฑ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์— ๋Œ€ํ•œ ์˜ˆ๋กœ ์„ฑ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋งŒ ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ์˜ˆ์ œ๋ฅผ ํ•ด์„ํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  ํšจ๊ณผ ํ˜ธ์ถœ์„ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์žˆ๋Š” ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ.

์‹ค์ œ๋กœ ๋‚ด๋ถ€ ์บ์‹œ๋ฅผ ๋ฌดํšจํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๋ฒˆ ์‚ฌ์šฉํ•œ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

useEffect(() => {
  if (props.invalidateCache) {
    cache.clear()
  }
}, [props.invalidateCache])

์ด๋Ÿฐ ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์ด ์˜๊ฒฌ์„ ๋ฌด์‹œํ•˜๊ณ  ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค.

@๋ฏธ์Šคํ„ฐ๋ฆฌ๋ณด
์ด๊ฑด ์–ด๋–ค๊ฐ€์š”

  const [parent, setParent] = useState(0);
  const [child, setChild] = useState(0);
  const updateChild = React.useCallback(() => setChild(0), [parent]);

  useEffect(
    () => {
      updateChild();
    },
    [updateChild] 
  );

๋‚˜๋„ ๋‹น์‹ ์˜ ๊ทธ ์กฐ๊ฐ์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ข…์†์„ฑ์€ ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ๋งŒ ๊ฐ€์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฒ„๊ทธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์ œ์•ˆ์ด ๋ฐ˜๋“œ์‹œ ํ•ด๊ฒฐ๋˜์ง€๋Š” ์•Š์ง€๋งŒ ์ ์–ด๋„ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ด์ „์— getDerivedStateFromProps ๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๊นŒ? getDerivedStateFromProps๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๊นŒ? ๋•๋‹ค?

@nghiepit ์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ๋ฌผ(์˜ˆ: CodeSandbox)์—์„œ ํ•„์ˆ˜ ์ฒดํฌ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฌด์‹œํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ“๊ธ€์„ ์ˆจ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ฒดํฌ๋ฆฌ์ŠคํŠธ์— ๋”ฐ๋ผ ๋‹ค์‹œ ๊ฒŒ์‹œํ•ด ์ฃผ์„ธ์š”. ๊ฐ์‚ฌ ํ•ด์š”.

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

@MrLeebo ๊ฐ€ ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฌธ์ œ/์ •์‹ ์  ๋ชจ๋ธ ์งˆ๋ฌธ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์ง๊ฐ์€ useEffect ์ข…์†์„ฑ ๊ทœ์น™์ด ๊ทธ๋ ‡๊ฒŒ ์—„๊ฒฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฐœ๋… ์ฆ๋ช… ์•„์ด๋””์–ด๋ฅผ ์œ„ํ•ด ์ž‘์—…ํ•˜๊ณ  ์žˆ๋˜ ๋ฏฟ์„ ์ˆ˜ ์—†์„ ์ •๋„๋กœ ์ธ์œ„์ ์ธ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด ์ฝ”๋“œ๊ฐ€ ํ˜•ํŽธ์—†๊ณ  ์•„์ด๋””์–ด๊ฐ€ ํŠนํžˆ ์œ ์šฉํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ, ๋‹น๋ฉดํ•œ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ข‹์€ ์˜ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. @MrLeebo๊ฐ€ ๋‚ด๊ฐ€ ๊ฝค ์ž˜ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์งˆ๋ฌธ์„ ํ‘œํ˜„ํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์„ฑ๋Šฅ ์ตœ์ ํ™”์™€ ์‹ค์ œ ๊ตฌ์„ฑ ์š”์†Œ ๋™์ž‘์„ ์œ„ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ํ•ด์„ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๋‹ฌ๋ ค ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. React Hooks FAQ๋Š” ์„ฑ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์— ๋Œ€ํ•œ ์˜ˆ๋กœ ์„ฑ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋งŒ ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ์˜ˆ์ œ๋ฅผ ํ•ด์„ํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  ํšจ๊ณผ ํ˜ธ์ถœ์„ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์žˆ๋Š” ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ.

https://codesandbox.io/s/5v9w81j244

ํŠนํžˆ useDelayedItems ์˜ useEffect ํ›„ํฌ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ items ์†์„ฑ์„ ์ข…์†์„ฑ ๋ฐฐ์—ด์— ํฌํ•จํ•˜๋ฉด linting ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ ํ•ด๋‹น ์†์„ฑ์ด๋‚˜ ๋ฐฐ์—ด์„ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๋ฉด ์›ํ•˜์ง€ ์•Š๋Š” ๋™์ž‘์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

useDelayedItems ํ›„ํฌ์˜ ๊ธฐ๋ณธ ์•„์ด๋””์–ด๋Š” ํ•ญ๋ชฉ ๋ฐฐ์—ด๊ณผ ๊ตฌ์„ฑ ๊ฐœ์ฒด(ms ๋‹จ์œ„ ์ง€์—ฐ, ์ดˆ๊ธฐ ํŽ˜์ด์ง€ ํฌ๊ธฐ)๊ฐ€ ์ฃผ์–ด์ง€๋ฉฐ, ์ฒ˜์Œ์—๋Š” ๊ตฌ์„ฑ๋œ ํŽ˜์ด์ง€ ํฌ๊ธฐ์— ๋”ฐ๋ผ ํ•ญ๋ชฉ์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. config.delay ๊ฐ€ ์ง€๋‚˜๋ฉด ํ•ญ๋ชฉ์€ ์ด์ œ ์ „์ฒด ํ•ญ๋ชฉ ์„ธํŠธ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ํ•ญ๋ชฉ ์„ธํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด ํ›„ํฌ๋Š” ์ด "์ง€์—ฐ" ๋…ผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„์ด๋””์–ด๋Š” ํฐ ๋ชฉ๋ก์˜ ์ง€์—ฐ๋œ ๋ Œ๋”๋ง์˜ ๋งค์šฐ ์กฐ์žกํ•˜๊ณ  ๋ฉ์ฒญํ•œ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.

์ด ๊ทœ์น™์— ๋Œ€ํ•œ ๋ชจ๋“  ์ž‘์—…์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœํ•  ๋•Œ ๋งค์šฐ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์˜ˆ์ œ์˜ ํ’ˆ์งˆ์ด ์˜์‹ฌ์Šค๋Ÿฝ๋”๋ผ๋„ ์ด๋Ÿฌํ•œ ์—ฐ์‚ฐ์ž๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‚จ์šฉ/์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ํ†ต์ฐฐ๋ ฅ์„ ์ œ๊ณตํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ๋‚˜๋Š” ํ–‰๋™ ์˜๋„์™€ ๊ด€๋ จ๋œ ์ฝ”๋“œ ๋ฐ ์ƒ์ž ๋‚ด๋ถ€์— ๋ช‡ ๊ฐ€์ง€ ๋ช…ํ™•ํ•œ ์„ค๋ช…์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ •๋ณด๊ฐ€ ์ถฉ๋ถ„ํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ์ ์ด ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค.

๋‹ค๋ฅธ ๊ฐ’์„ ๊ฒฐํ•ฉํ•œ ๋‹จ์ผ ๊ฐ’์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ?

์˜ˆ: fullName์€ firstName ๋ฐ lastName ์—์„œ ํŒŒ์ƒ๋ฉ๋‹ˆ๋‹ค. fullName ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ํšจ๊ณผ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ณ (์˜ˆ: ์‚ฌ์šฉ์ž๊ฐ€ "์ €์žฅ"์„ ๋ˆŒ๋ €์„ ๋•Œ) ํšจ๊ณผ์—์„œ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐ’์—๋„ ์•ก์„ธ์Šคํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ๋ชจ

fullName ๊ฐ€ ๋ณ€๊ฒฝ๋œ ํ›„์— firstName ๋˜๋Š” lastName ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

@aweary useEffect ์†Œํ’ˆ ๋ณ€๊ฒฝ ๊ฐ„์ ‘ ์ฐธ์กฐ์—์„œ ์–ด๋–ค ๊ฐ€์น˜๋ฅผ ์–ป๊ณ  ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. onClick ์ด "ํšจ๊ณผ"๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

https://codesandbox.io/s/0m4p3klpyw

๋‹ค๋ฅธ ๊ฐ’์„ ๊ฒฐํ•ฉํ•˜๋Š” ๋‹จ์ผ ๊ฐ’์— ๊ด€ํ•ด์„œ๋Š” useMemo ๊ฐ€ ์•„๋งˆ๋„ ์›ํ•˜๋Š” ๋Œ€๋กœ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ์—์„œ ๊ณ„์‚ฐ์˜ ์ง€์—ฐ๋œ ํŠน์„ฑ์€ ์—ฐ๊ฒฐ๋œ ๋™์ž‘๊ณผ ์ •ํ™•ํžˆ 1:1๋กœ ๋งคํ•‘๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ์— ๋Œ€ํ•œ ์ฝ”๋“œ ๋ฐ ์ƒ์ž ๋งํฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์ด ๊ฒŒ์‹œ๋ฌผ์„ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค.

๋งค์šฐ ๊ฐ„๋‹จํ•œ ๊ทœ์น™์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ํƒญ์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ ๋งจ ์œ„๋กœ ์Šคํฌ๋กคํ•ฉ๋‹ˆ๋‹ค.
https://codesandbox.io/s/m4nzvryrxj

useEffect(() => {
    window.scrollTo(0, 0);
  }, [activeTab]);

๊ทธ๋ฆฌ๊ณ  React Hook useEffect has an unnecessary dependency: 'activeTab'. Either exclude it or remove the dependency array ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ผ๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ๋•Œ componentDidMount ๋™์ž‘์„ ๋ณต์ œํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

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

์ด ๊ทœ์น™์€ ์ด๊ฒƒ์— ๋Œ€ํ•ด ์—ด์‹ฌํžˆ ๋ถˆํ‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. useEffect ๋ฐฐ์—ด์— ๋ชจ๋“  ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์ฃผ์ €ํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ useEffect ์ „์— ์ƒˆ ์ธ๋ผ์ธ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฉ๋‹ˆ๋‹ค.
https://codesandbox.io/s/nr7wz8qp7l

const foo = () => {...};
useEffect(() => {
    foo();
  }, []);

๋‹น์‹ ์€ ์–ป์„: React Hook useEffect has a missing dependency: 'foo'. Either include it or remove the dependency array
์ข…์†์„ฑ ๋ชฉ๋ก์— foo๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ๋Š๋ผ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋ Œ๋”์—์„œ foo๋Š” ์ƒˆ๋กœ์šด ํ•จ์ˆ˜์ด๊ณ  useEffect๋Š” ํ•ญ์ƒ ์‹คํ–‰๋ฉ๋‹ˆ๊นŒ?

@ksaldana1 ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์— ๋ถ€์ž‘์šฉ์„ ๋„ฃ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์‹ค์ œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ปค๋ฐ‹๋˜๊ธฐ ์ „์— ๋ถ€์ž‘์šฉ์ด ๋ฐœ์ƒํ•˜์—ฌ ์›ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ์ž์ฃผ ๋ถ€์ž‘์šฉ์ด ํŠธ๋ฆฌ๊ฑฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— useReducer ์‚ฌ์šฉํ•  ๋•Œ๋„ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๊ฐ’์„ ๊ฒฐํ•ฉํ•˜๋Š” ๋‹จ์ผ ๊ฐ’์— ๊ด€ํ•ด์„œ๋Š” useMemo ๊ฐ€ ์•„๋งˆ๋„ ์›ํ•˜๋Š” ๊ฐ’์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์˜ˆ์—์„œ useMemo ํ•˜๋ฉด firstName ๋˜๋Š” lastName ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค useMemo ๊ฐ€ ์ƒˆ fullName ํŒŒ์ƒํ•˜๋ฏ€๋กœ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋™์ž‘์€ ์ €์žฅ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ๋•Œ๊นŒ์ง€ fullName ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@weary ์ด๋Ÿฐ ์‹์œผ๋กœ ์ž‘๋™ํ• ๊นŒ์š”? https://codesandbox.io/s/lxjm02j50m
๊ถŒ์žฅ ๊ตฌํ˜„์ด ๋ฌด์—‡์ธ์ง€ ๋งค์šฐ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ๋ง์”€ํ•˜์‹  ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ๋” ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

ํ•ธ๋“ค๋Ÿฌ์˜ ํŠธ๋ฆฌ๊ฑฐ๋ง ๋ฐ ํšจ๊ณผ:

์‹ค์ œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ปค๋ฐ‹๋˜๊ธฐ ์ „์— ๋ถ€์ž‘์šฉ์ด ๋ฐœ์ƒํ•˜์—ฌ ์›ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ์ž์ฃผ ๋ถ€์ž‘์šฉ์ด ํŠธ๋ฆฌ๊ฑฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ useReducer ์ƒํƒœ ์‚ฌ์šฉ:

์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌ ํ•ด์š”!

@bugzpodder ์ข…๋ฅ˜ ๋ฌด๊ด€์˜ํ•˜์ง€๋งŒ ์Šคํฌ๋กค ํ˜ธ์ถœ์€ ๋‚ด๋ถ€์— ์žˆ์–ด์•ผํ•œ๋‹ค useLayoutEffect ๋Œ€์‹  useEffect . ํ˜„์žฌ ์ƒˆ ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•  ๋•Œ ๋ˆˆ์— ๋„๋Š” ๊นœ๋ฐ•์ž„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์˜๋„์ ์ธ ๊ฒƒ์ธ์ง€ ์•„๋‹Œ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:

props์—์„œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ linter๋Š” ์ „์ฒด props ๊ฐœ์ฒด๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

์งง์€ ๋ฒ„์ „:

useEffect(function() {
  props.setLoading(true)
}, [props.setLoading])

// โš ๏ธ React Hook useEffect has a missing dependency: 'props'.

์ •์‹ ๋ฒ„์ „: ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค

๋‹ค์‹œ ์‹œ๋„ํ•˜์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ๋” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค ;)

์†Œํ’ˆ์—์„œ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜ ์‹ค์ œ๋กœ ์–ด๋””์—์„œ๋“  ํ›„ํฌ ๋‚ด๋ถ€์—์„œ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด exhaustive-deps ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ข…์†์„ฑ ๋ฐฐ์—ด์— ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ํ•จ์ˆ˜์ด๊ณ  ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

-> ์ƒŒ๋“œ๋ฐ•์Šค

๊ทธ๊ฒƒ์ด ๋‹น์‹ ์ด ํ•„์š”๋กœํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ์ด๊ธฐ๋ฅผ ํฌ๋งํ•˜์ง€๋งŒ ๋‚ด๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ํ–ˆ์Šต๋‹ˆ๋‹ค .

๊ณ ๋งˆ์›Œ.

๋”ฐ๋ผ์„œ ์ข…์†์„ฑ ๋ฐฐ์—ด์— ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ํ•จ์ˆ˜์ด๊ณ  ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ ์ •ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋Š” ๋ถ€๋ชจ๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋งํ•  ๋•Œ ํ•ญ์ƒ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@siddharthkp

props์—์„œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ linter๋Š” ์ „์ฒด props ๊ฐœ์ฒด๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ props.foo() ๊ฐ€ this ๋ฅผ foo ํ˜ธ์ถœ๋กœ props ์ž์ฒด๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ foo ๋Š” ์•”์‹œ์ ์œผ๋กœ props ์— ์˜์กดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ์—๋Š” ๋” ๋‚˜์€ ๋ฉ”์‹œ์ง€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ํ•ญ์ƒ ๊ตฌ์กฐ๋ฅผ ๋ถ„ํ•ดํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•จ์ˆ˜๋Š” ๋ถ€๋ชจ๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋งํ•  ๋•Œ ํ•ญ์ƒ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก , ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๊ฐ€ ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ •์˜๋œ ๊ฒฝ์šฐ์—๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก , ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๊ฐ€ ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ •์˜๋œ ๊ฒฝ์šฐ์—๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

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

thx @gaearon

์ด๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ props.foo() ๊ฐ€ this ๋ฅผ foo ํ˜ธ์ถœ๋กœ props ์ž์ฒด๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ foo ๋Š” ์•”์‹œ์ ์œผ๋กœ props ์— ์˜์กดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ์—๋Š” ๋” ๋‚˜์€ ๋ฉ”์‹œ์ง€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ํ•ญ์ƒ ๊ตฌ์กฐ๋ฅผ ๋ถ„ํ•ดํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ๋‚ด ์งˆ๋ฌธ์—๋„ ๋Œ€๋‹ตํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ˜„

https://codesandbox.io/s/98z62jkyro

๊ทธ๋ž˜์„œ ๊ฐ ์ž…๋ ฅ์ด ์Šค์Šค๋กœ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋„๋ก ์ปจํ…์ŠคํŠธ์— ๋…ธ์ถœ๋œ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์ž…๋ ฅ์„ ๋“ฑ๋กํ•˜์—ฌ ์ž…๋ ฅ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. useRegister๋ผ๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์ „:

 useEffect(
    () => {
      register(props.name, props.rules || []);
      console.log("register");
      return function cleanup() {
        console.log("cleanup");
        unregister(props.name);
      };
    },
    [props.name, props.rules, register, unregister]
  );

props.rules๋ฅผ ์ข…์†์„ฑ์˜ ์ผ๋ถ€๋กœ ๊ฐ•์ œํ•  ๋•Œ ๋ฌดํ•œ ๋ Œ๋” ๋ฃจํ”„๋กœ ๋๋‚˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. Props.rules๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ๋กœ ๋“ฑ๋กํ•  ํ•จ์ˆ˜์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ์–ด๋ ˆ์ด๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์ œ๊ณตํ•  ๋•Œ๋งŒ ์ด ๋ฌธ์ œ๋ฅผ ๊ฐ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ ์ฝ˜์†”์„ ์—ฌ๋Š” ๋ฃจํ”„๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

props.name์„ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์˜๋„ํ•œ ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ง€์ ํ•œ ๋Œ€๋กœ ์ข…์†์„ฑ์„ ์ ์šฉํ•˜๋ฉด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋˜๋ฉฐ ์ด ๊ฒฝ์šฐ ๋ถ€์ž‘์šฉ์ด ์‹ฌ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@bugzpodder

์žฌ: https://github.com/facebook/react/issues/14920#issuecomment -467212561

useEffect(() => {
    window.scrollTo(0, 0);
  }, [activeTab]);

์ด๊ฒƒ์€ ์ ๋ฒ•ํ•œ ์ผ€์ด์Šค์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ํšจ๊ณผ์— ๋Œ€ํ•ด์„œ๋งŒ ๊ด€๋ จ ์—†๋Š” deps๋ฅผ ํ—ˆ์šฉํ•˜๋„๋ก ๊ฒฝ๊ณ ๋ฅผ ์™„ํ™”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. (ํ•˜์ง€๋งŒ useMemo ๋˜๋Š” useCallback .)

๋˜ํ•œ ์ผ๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ๋•Œ componentDidMount ๋™์ž‘์„ ๋ณต์ œํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
์ด ๊ทœ์น™์€ ์ด๊ฒƒ์— ๋Œ€ํ•ด ์—ด์‹ฌํžˆ ๋ถˆํ‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. useEffect ๋ฐฐ์—ด์— ๋ชจ๋“  ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์ฃผ์ €ํ•ฉ๋‹ˆ๋‹ค.

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ์˜ˆ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์œผ์…”์„œ ๋…ผ์˜ํ•  ๊ธฐํšŒ๋ฅผ ๋†“์ณค์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ OP ๊ฒŒ์‹œ๋ฌผ ์ด ๊ตฌ์ฒด์ ์ธ UI ์˜ˆ์ œ ๋ฅผ

๋งˆ์ง€๋ง‰์œผ๋กœ useEffect ์ „์— ์ƒˆ ์ธ๋ผ์ธ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. https://codesandbox.io/s/nr7wz8qp7l

์ด ๊ฒฝ์šฐ doSomething ๋ฅผ ํšจ๊ณผ๋กœ ์˜ฎ๊ธฐ๋ฉด ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์„ ์–ธํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋˜๋Š” useCallback ์ฃผ์œ„์— doSomething ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ์–ธ๋œ dep๋งŒ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ทœ์น™์„ ์™„ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ์žˆ๊ณ  ์ด๋Ÿฌํ•œ ํ•จ์ˆ˜ ์ค‘ ํ•˜๋‚˜์— prop ๋˜๋Š” state๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ ํ˜ผ๋™๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ‘์ž๊ธฐ ๊ทธ๊ฒƒ์„ ์ „์ด์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ํšจ๊ณผ ๋Ž์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์ƒˆ ๊ทœ์น™์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ ์š”์ฒญ์ธ์ง€ ์•„๋‹ˆ๋ฉด exhaustive-deps ๋Œ€ํ•ด ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌํ•ญ์ธ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

import React from 'react'
import emitter from './thing'

export const Foo = () => {
  const onChange = () => {
    console.log('Thing changed')
  }

  React.useEffect(() => {
    emitter.on('change', onChange)
    return () => emitter.off('change', onChange)
  }, [onChange])

  return <div>Whatever</div>
}

onChange ํ•จ์ˆ˜๋Š” ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— useEffect hook [onChange] ์ธ์ˆ˜๋Š” ์ค‘๋ณต๋˜๋ฉฐ ์ œ๊ฑฐ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

   React.useEffect(() => {
     emitter.on('change', onChange)
     return () => emitter.off('change', onChange)
-  }, [onChange])
+  })

๋ฆฐํ„ฐ๊ฐ€ ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๋ฐฐ์—ด ์ธ์ˆ˜๋ฅผ ์‚ญ์ œํ•˜๋„๋ก ์กฐ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐ์—ด ํ•ญ๋ชฉ ๋ชฉ๋ก์„ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ๊ทธ ์ค‘ ํ•˜๋‚˜ ์ด์ƒ์ด ์ƒ์„ฑ๋˜๊ณ  ์–ด์จŒ๋“  ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค ํ›„ํฌ๊ฐ€ ๋ฌดํšจํ™”๋˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ซ๋Š” ์ƒํ™ฉ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ทœ์น™์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ˆ˜์ • ์‚ฌํ•ญ๊ณผ ๋” ๋‚˜์€ ๋ฉ”์‹œ์ง€๊ฐ€ ํฌํ•จ๋œ [email protected] ์„ ์ถœ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. ํš๊ธฐ์ ์ธ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€๋Š” ๋‹ค์Œ์ฃผ์— ๋ด์•ผ๊ฒ ๋‹ค.

๋˜ํ•œ https://github.com/facebook/react/pull/14996์— "์•ˆ์ „ํ•œ" ๊ธฐ๋Šฅ deps๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋Š” ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋ฅผ ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค

@gaearon ์ข‹์€ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋” ๋‚˜์€ ์Šคํƒ€์ผ์„ ๊ฐ–๋Š” ๋ฐ ํ™•์‹คํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค ๐Ÿ™

@gaearon ์•ก์…˜์ด prop์—์„œ ์˜ค๋Š” ๊ฒฝ์šฐ์—๋Š” ์—ฌ์ „ํžˆ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ๋ฅผ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

image

์—ฌ๊ธฐ์„œ setScrollTop ๋Š” redux ์ž‘์—…์ž…๋‹ˆ๋‹ค.

Slider ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ด ์˜ˆ์—์„œ๋Š” useEffect ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ DOM์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜์—ฌ noUiSlider ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งˆ์šดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํšจ๊ณผ๊ฐ€ ์‹คํ–‰๋  ๋•Œ DOM์—์„œ ref๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก [sliderElement] ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ตฌ์„ฑ ์š”์†Œ๋„ ์„œ๋ฒ„๋กœ ๋ Œ๋”๋งํ•˜๋ฏ€๋กœ ๋ Œ๋”๋ง ์ „์— DOM์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. useEffect ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์†Œํ’ˆ(์ฆ‰, min, max, onUpdate ๋“ฑ)์€ ์ƒ์ˆ˜์ด๋ฏ€๋กœ ํšจ๊ณผ์— ์ „๋‹ฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

screen shot 2019-03-02 at 5 17 09 pm


๋‹ค์Œ์€ ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํšจ๊ณผ์ž…๋‹ˆ๋‹ค.

const { min, max, step } = props;
const sliderElement = useRef();

useEffect(() => {
  if (!sliderElement.current) {
    return;
  }

  const slider = sliderElement.current;
  noUiSlider.create(slider, {
    connect: true,
    start: [min, max],
    step,
    range: {
      min: [min],
      max: [max],
    },
  });

  if (props.onUpdate) {
    slider.noUiSlider.on('update', props.onUpdate);
  }

  if (props.onChange) {
    slider.noUiSlider.on('change', props.onChange);
  }
}, [sliderElement]);

@WebDeg-Brian ์ „์ฒด CodeSandbox ๋ฐ๋ชจ ์—†์ด๋Š” ๋‹น์‹ ์„ ๋„์šธ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ƒ๋‹จ ๊ฒŒ์‹œ๋ฌผ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๋‚˜๋Š” ์ผ๋ฐ˜์ ์ธ "๊ธฐ๋Šฅ์€ ์ ˆ๋Œ€ ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค"๋ผ๋Š” ์˜คํ•ด์— ๋Œ€ํ•ด ์•ฝ๊ฐ„์˜ ๊ธ€์„ ์˜ฌ๋ ธ์Šต๋‹ˆ๋‹ค.

https://overreacted.io/how-are-function-components-different-from-classes/

์™„์ „ํžˆ ๊ฐ™์€ ์ฃผ์ œ๋Š” ์•„๋‹ˆ์ง€๋งŒ ์ด ๊ทœ์น™๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @gaearon๋‹˜ , ์—ฌ๊ธฐ์— ๊ฒŒ์‹œํ•˜๋„๋ก ์š”์ฒญํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค(ํŠธ์œ„ํ„ฐ์—์„œ) :)

๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ˜์‘ ํŠธ๋žฉ ์„ ํ›„ํฌ๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ์š”์†Œ ์™ธ๋ถ€/๋‚ด๋ถ€์˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ํŠธ๋žฉ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

๋‚ด ๋ฌธ์ œ๋Š” useEffect ์ด ์ƒํƒœ ๊ฐ’( trapped )์— ์˜์กด ํ•˜์ง€ ์•Š์œผ๋ฉด ๋•Œ๋•Œ๋กœ ๋ถ€์‹คํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์˜๊ฒฌ๊ณผ ๋กœ๊ทธ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. useTrap.js ํŒŒ์ผ์„ ๋ณด๋ฉด ์ฃผ์„๊ณผ ๋กœ๊ทธ๊ฐ€ useEffect ๋ฐ preventDefaultHelper ํ•จ์ˆ˜์— ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์•„๋Š” ํ•œ, ๊ฐ’์ด useEffect ์•ˆ์— ์žˆ์ง€ ์•Š์œผ๋ฉด ์ข…์†์„ฑ์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(๋‚ด๊ฐ€ ํ‹€๋ ธ๋‹ค๋ฉด ์ •์ •ํ•ด ์ฃผ์„ธ์š”).

  1. ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค
  2. ๋‹จ๊ณ„:
    ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ์ž ๋‚ด๋ถ€๋ฅผ ํด๋ฆญํ•˜์—ฌ ํ™œ์„ฑํ™”ํ•˜๊ณ  ์™ธ๋ถ€๋ฅผ ํด๋ฆญํ•˜์—ฌ ํ™œ์„ฑํ™”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๋Š” ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ฒซ ๋ฒˆ์งธ ํด๋ฆญ์˜ ๊ฒฝ์šฐ ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด( e.preventDefault ).
    ๋‚ด๊ฐ€ "์ฒซ ๋ฒˆ์งธ ํด๋ฆญ"์ด๋ผ๊ณ  ๋งํ•˜๋ฉด ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ํด๋ฆญ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
    ํ™œ์„ฑ ์ƒ์ž๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ƒ์ž ์™ธ๋ถ€๋ฅผ ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ์œผ๋กœ ํด๋ฆญํ•˜๋ฉด ์ƒํƒœ๊ฐ€ "๋น„ํ™œ์„ฑ"์œผ๋กœ ๋ณ€๊ฒฝ๋˜๊ณ  ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™ธ๋ถ€์—์„œ ๋‹ค๋ฅธ ํด๋ฆญ์€ ์ƒํƒœ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด๊ฐ€ ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ๋ช…ํ™•ํ•˜๊ณ  ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์•Œ๋ ค์ฃผ์„ธ์š”. ๊ฐ์‚ฌ ํ•ด์š”!

์•ˆ๋…•ํ•˜์„ธ์š” @gaearon ๋‹˜ , Twitter์—์„œ ์ œ์•ˆํ•œ ๋Œ€๋กœ ์—ฌ๊ธฐ์— ๋งž์ถค ํ›…์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค! ์ข…์†์„ฑ์„ ๊ฑด๋„ˆ ๋›ฐ์ง€ ์•Š๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ชจ์–‘์„ ์ฐพ๊ธฐ ์œ„ํ•ด ๊ณ ์‹ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜๋‚˜์˜ ์˜ˆ์‹œ๋กœ ์ •๊ตํ•˜๊ฒŒ ์„ค๋ช…๋˜์–ด ์žˆ์œผ๋‹ˆ ๋ช…ํ™•ํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ํ˜„์žฌ ์ƒํƒœ์ž…๋‹ˆ๋‹ค: react-async-utils/src/hooks/useAsyncData.ts

๊ธฐ๋Šฅ ๊ฐœ์š”
์‚ฌ์šฉ์ž๊ฐ€ ๋น„๋™๊ธฐ ํ˜ธ์ถœ, ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ ๋ฐ ํ”„๋กœ์„ธ์Šค์˜ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.

triggerAsyncData ๋Š” Promise ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” getData ํ•จ์ˆ˜์— ๋”ฐ๋ผ asyncData ์ƒํƒœ๋ฅผ ๋น„๋™๊ธฐ์‹์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. triggerAsyncData ๋Š” ํšจ๊ณผ๋กœ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ํ›„ํฌ ์‚ฌ์šฉ์ž๊ฐ€ "์ˆ˜๋™์œผ๋กœ" ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋„์ „

  1. triggerAsyncData ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํšจ๊ณผ์˜ ์ข…์†์„ฑ์€ ๋ณธ์งˆ์ ์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. triggerAsyncData ๋Š” ํšจ๊ณผ์˜ ์ข…์†์„ฑ์ด์ง€๋งŒ ๋ชจ๋“  ๋ Œ๋”๋ง์—์„œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€์˜ ์ƒ๊ฐ:

    1. ์ข…์†์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค => ํ•˜์ง€๋งŒ ํšจ๊ณผ๋Š” ๋ชจ๋“  ๋ Œ๋”์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

    2. ์ข…์†์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•˜๋˜ triggerAsyncData => useMemo / useCallback ์™€ ํ•จ๊ป˜ useMemo / useCallback ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ ์ตœ์ ํ™”์—๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. AFAIK.

    3. ๋ฒ”์œ„ ๋‚ด์—์„œ ํšจ๊ณผ => ๊ทธ๋Ÿฌ๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

    4. triggerAsyncData ๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  triggerAsyncData ์˜ ์ข…์†์„ฑ์„ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉ => ์ง€๊ธˆ๊นŒ์ง€ ์ฐพ์€ ์ตœ์ƒ์˜ ์˜ต์…˜. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์€ "exhaustive-deps" ๊ทœ์น™์„ ์–ด๊น๋‹ˆ๋‹ค.

  2. ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ์˜ ๋ชจ๋“  ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋‚ด๋ถ€ ํšจ๊ณผ์˜ ์ข…์†์„ฑ์ด ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ธ๋ผ์ธ ํ•จ์ˆ˜์™€ ๋ฆฌํ„ฐ๋Ÿด ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋ฉด ํšจ๊ณผ๊ฐ€ ๋„ˆ๋ฌด ์ž์ฃผ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

    1. ์ฑ…์ž„์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋งก๊ธฐ์‹ญ์‹œ์˜ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ useMemo / useCallback ์‚ฌ์šฉํ•˜์—ฌ ์ ์ ˆํ•œ ๊ฐ’์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. => ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋“ค์ด ํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ์•„์ฃผ ์žฅํ™ฉํ•ฉ๋‹ˆ๋‹ค.

    2. ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ธ์ˆ˜๋ฅผ ํ—ˆ์šฉํ•˜์—ฌ ์ž…๋ ฅ์˜ ๊นŠ์ด๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์ž…๋ ฅ ์ž์ฒด ๋Œ€์‹  ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ "exhaustive-deps" ๊ทœ์น™์„ ์–ด๊น๋‹ˆ๋‹ค. (์‹ค์ œ๋กœ ๋‚˜๋Š” ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ถ”๊ฐ€ ์ธ์ˆ˜๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š์œผ๋ฉด ์ผ๋ฐ˜ deps๋กœ ๋˜๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ๊ฐ•๋ ฅํ•œ ํŒจํ„ด์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.)

  3. ์‚ฌ์šฉ์ž ์ง€์ • ํ›„ํฌ์— ๋Œ€ํ•ด ์ œ๋Œ€๋กœ ๊ด€๋ฆฌ๋˜์ง€ ์•Š๋Š” ์ข…์†์„ฑ์€ ๋‚ด๋ถ€ ํšจ๊ณผ๋กœ ์ธํ•ด ๋ฌดํ•œ ๋น„๋™๊ธฐ ๋ฃจํ”„๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฉ์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ "๊ฐ€์งœ"๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๊นŒ? ์ข…์†์„ฑ( asyncData ). ์ด๊ฒƒ์€ "exhaustive-deps" ๊ทœ์น™์„ ๋‹ค์‹œ ๊นจ๋œจ๋ฆฝ๋‹ˆ๋‹ค.

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

์—ฌ๊ธฐ์—์„œ ๋ชจ๋“  ๋…ธ๋ ฅ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

@gaearon ๋‹˜

  1. ์ตœ์†Œํ•œ์˜ ๋น„๋™๊ธฐ์‹ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ์˜ˆ์ œ CodeSandbox ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

  2. ์‚ฌ์šฉ์ž๋Š” json api ์—์„œ ๊ฐ€์ ธ์˜จ 5๊ฐœ์˜ lorem ipsum ์ œ๋ชฉ ๋ฌธ์ž์—ด์„ ๋ณผ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค.

  3. ์˜๋„ํ•œ API๋กœ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์œ„ํ•œ ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

const { data, isLoading, isError } = useDataApi('https://jsonplaceholder.typicode.com/posts')

์‚ฌ์šฉ์ž ์ •์˜ useDataApi ํ›„ํฌ์˜ ๋‚ด๋ถ€:

...
  const fetchData = async () => {
    let response;
    setIsError(false);
    setIsLoading(true);

    try {
      response = await fetch(url).then(response => response.json());

      setData(response);
    } catch (error) {
      setIsError(true);
    }

    setIsLoading(false);
  };

  useEffect(
    () => {
      fetchData();
    },
    [url]
  );
...

๋ฌธ์ œ๋Š” ์ด ์ฝ”๋“œ

  useEffect(
    () => {
      fetchData();
    },
    [url]
  );

์—ฌ๊ธฐ์„œ react-hooks/exhaustive-deps ๋Š” ๋‚ด ์ข…์†์„ฑ ๋ฐฐ์—ด์— fetchData ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  url ๋ฅผ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒฝ๊ณ ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ด ํ›„ํฌ๋ฅผ ๋‹ค์Œ์œผ๋กœ ๋ฐ”๊พธ๋ฉด

  useEffect(
    () => {
      fetchData();
    },
    [fetchData]
  );

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ง€์†์ ์œผ๋กœ ์š”์ฒญ์„ ์‹คํ–‰ํ•˜๊ณ  ์ ˆ๋Œ€ ๋ฉˆ์ถ”์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฌผ๋ก  ํฐ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๋‚ด ์ฝ”๋“œ์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š”์ง€ ๋˜๋Š” react-hooks/exhaustive-deps ๊ฐ€ ๊ฐ€์–‘์„ฑ์„ ์‹คํ–‰ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋„์›€์„ ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ •๋ง ๊ณ ๋งˆ์›Œ.

์ถ”์‹ : useEffect๊ฐ€ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์— ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ท€ํ•˜์˜ ์˜๊ฒฌ์„ ์ฝ์—ˆ์ง€๋งŒ, ๋ฐ˜์‘ ๋ฌธ์„œ ๋Š” useEffect ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์— ์ ํ•ฉํ•˜๋‹ค๋Š” ํ™•์‹ ์„ ์ฃผ๋Š” Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects ๋ผ๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ง€๊ธˆ์€ ์กฐ๊ธˆ ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค ๐Ÿ˜•

@jan-stehlik fetchData๋ฅผ useCallback์œผ๋กœ ๋ž˜ํ•‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. https://codesandbox.io/s/pjmjxprp0m ์—์„œ ํ•„์š”ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์œผ๋กœ ๊ท€ํ•˜์˜ ์ฝ”๋“œ ๋ฐ ์ƒ์ž๋ฅผ ๋ถ„๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋งค์šฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค .

๋‚ด๊ฐ€ ์•„๋Š” ํ•œ ๊ฐ’์ด useEffect ๋‚ด๋ถ€์— ์—†์œผ๋ฉด ์ข…์†์„ฑ์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํ‹€๋ฆฐ ๊ฒฝ์šฐ ์ˆ˜์ •).

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

ํฅ๋ฏธ๋กœ์šด.

ํšจ๊ณผ ๋‚ด์—์„œ handleEvent๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹น์‹ ์€ ๊ทธ๊ฒƒ์„ ์„ ์–ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ฝ๋Š” ๊ฐ’์ด ์˜ค๋ž˜๋œ ์ด์œ ์ž…๋‹ˆ๋‹ค.

_"ํ•˜์ง€๋งŒ ๋‹น์‹ ์€ ๊ทธ๊ฒƒ์„ ์„ ์–ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค"_์€(๋Š”) ๋ฌด์Šจ ๋œป์ธ๊ฐ€์š”?
ํšจ๊ณผ ์•„๋ž˜์— ์„ ์–ธ๋ฉ๋‹ˆ๋‹ค(๋‹ค๋ฅธ ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ์™€ ๋™์ผ).

์•„๋‹ˆ๋ฉด ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ƒํƒœ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ณ  ํšจ๊ณผ๊ฐ€ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํšจ๊ณผ๊ฐ€ ํ•ด๋‹น ์ƒํƒœ ๊ฐ’์— ์˜์กดํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

์•„๋‹ˆ๋ฉด ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ƒํƒœ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ณ  ํšจ๊ณผ๊ฐ€ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํšจ๊ณผ๊ฐ€ ํ•ด๋‹น ์ƒํƒœ ๊ฐ’์— ์˜์กดํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

์˜ˆ,์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ค‘ ํ•˜๋‚˜๋Š” deps์— ์„ ์–ธ (๊ทธ ๊ฒฝ์šฐ๋กœ ํฌ์žฅํ•œ๋‹ค useCallback ์„ ๋‹ค์‹œ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด), ๋˜๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ ์‚ฌ์šฉ.

์ข‹์•„ ์ด๊ฒƒ์€ ๋‚˜์—๊ฒŒ ์ƒˆ๋กœ์šด ์†Œ์‹์ด๋‹ค! @gaearon์„ ์ž…๋ ฅํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค :)
๋‚˜๋Š” ๋‹จ์ง€ ๊ทธ๊ฒƒ์ด ๋‚˜(๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ?)

ํšจ๊ณผ๊ฐ€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ, ์ „๋‹ฌ ๋˜๋Š” ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น deps ๋ฐฐ์—ด์— ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ํ•จ์ˆ˜ ์ž์ฒด ๋˜๋Š” ์ด ํ•จ์ˆ˜๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.
ํ•จ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ/์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ ๋‚ด์—์„œ ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ๊ฒฝ์šฐ ๊ตฌ์„ฑ ์š”์†Œ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ์ƒ์„ฑ๋˜์ง€ ์•Š๋„๋ก useCallback ๋กœ ๊ฐ์‹ธ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋ฌธ์„œ์—์„œ ๊ทธ๊ฒƒ์„ ๋ณด์ง€ ๋ชปํ–ˆ๋‹ค๊ณ  ๋งํ•ด์•ผ ํ•œ๋‹ค.
_Note_ ์„น์…˜์— ์ถ”๊ฐ€ํ•ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๊นŒ?

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

ํŽธ์ง‘ํ•˜๋‹ค
ํ•œ ๊ฐ€์ง€ ๋”, ๋‚ด ์˜ˆ์—์„œ handleEvent (๋˜๋Š” ๊ทธ๋Ÿฌํ•œ ์ด์œ ๋กœ ๋‹ค๋ฅธ ํ•ธ๋“ค๋Ÿฌ)๋ฅผ ๋ž˜ํ•‘ํ•  ๋•Œ useCallback ๋Œ€ํ•œ dep๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? event ์ž์ฒด์ธ๊ฐ€์š”?

๋‚˜๋Š” ๋ฌธ์„œ์—์„œ ๊ทธ๊ฒƒ์„ ๋ณด์ง€ ๋ชปํ–ˆ๋‹ค๊ณ  ๋งํ•ด์•ผ ํ•œ๋‹ค.

๋ฌธ์„œ์—๋Š” "ํšจ๊ณผ ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ฐธ์กฐ๋˜๋Š” ๋ชจ๋“  ๊ฐ’์ด ์ž…๋ ฅ ๋ฐฐ์—ด์—๋„ ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค"๋ผ๊ณ  ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ๋„ ๊ฐ€์น˜์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ด๊ฒƒ์„ ๋” ์ž˜ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ด ์Šค๋ ˆ๋“œ์˜ ์ „๋ถ€์ž…๋‹ˆ๋‹ค :-) ๋‚˜๋Š” ์ด๊ฒƒ์— ๊ด€ํ•œ ์ƒˆ ๋ฌธ์„œ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ๋”, ๋‚ด ์˜ˆ์—์„œ handleEvent(๋˜๋Š” ๊ทธ๋Ÿฌํ•œ ์ด์œ ๋กœ ๋‹ค๋ฅธ ํ•ธ๋“ค๋Ÿฌ)๋ฅผ ๋ž˜ํ•‘ํ•  ๋•Œ useCallback์˜ dep๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ด๋ฒคํŠธ ์ž์ฒด์ธ๊ฐ€์š”?

๋‹น์‹ ์ด ๋ฌด์Šจ ๋œป์ธ์ง€ ํ™•์‹คํ•˜์ง€. ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋“  ๊ฐ’์ž…๋‹ˆ๋‹ค. useEffect ์—์„œ์ฒ˜๋Ÿผ.

๋‚˜๋Š” ์ด๊ฒƒ์„ ์ข…์†์„ฑ์œผ๋กœ ํ•จ์ˆ˜๋กœ ์ƒ๊ฐํ•˜์ง€ ์•Š์•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์ •์‹  ๋ชจ๋ธ์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ / ํ›„ํฌ์— ์†Œํ’ˆ์ด๋‚˜ ์ธ์ˆ˜๋กœ ๋“ค์–ด์˜จ ๊ฒฝ์šฐ์—๋งŒ ์ข…์†์„ฑ์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋ฅผ ์œ„ํ•ด ์ด๊ฒƒ์„ ๋ช…ํ™•ํžˆ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

useCallback ์— ๊ด€ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

const memoHandleEvent = useCallback(
    handleEvent
);

๋ฌผ๋ก  ์ „๋‹ฌ memoHandleEvent ํ•˜๋Š” ์ข…์†์„ฑ useEffect ์›ฐ์— ๊ด€ํ•ด์„œ addEventListener INSEAD ์‹ค์ œ์˜ handleEvent ๊ธฐ๋Šฅ. ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™์œผ๋ฉด ์ด๊ฒƒ์ด ์ ์ ˆํ•˜๊ณ  ๊ด€์šฉ์ ์ธ ๋ฐฉ๋ฒ•์ด๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ฐธ๊ณ  ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๊ฐ€ ์—†๋Š” useCallback ๋Š” ์•„๋ฌด ์ž‘์—…๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ ์™„์ „ํ•œ ์ƒŒ๋“œ๋ฐ•์Šค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๋ถˆ์™„์ „ํ•œ ์„ค๋ช…์œผ๋กœ ์ˆ˜์ • ์‚ฌํ•ญ์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๊ฐ€ ์—†๋Š” useCallback์€ ์•„๋ฌด ์ž‘์—…๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์•„๋ฅด๊ทธ! :์ฐก๊ธ‹:ใ…‹ใ…‹ใ…‹

๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ ์™„์ „ํ•œ ์ƒŒ๋“œ๋ฐ•์Šค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๋ถˆ์™„์ „ํ•œ ์„ค๋ช…์œผ๋กœ ์ˆ˜์ • ์‚ฌํ•ญ์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์•„, ์ด๊ฒƒ์€ ์œ„์—์„œ ๋™์ผํ•œ ๋งํฌ ์ž…๋‹ˆ๋‹ค. ๋ฐฉ๊ธˆ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค :)

CodeSandbox ๋งํฌ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. PI๋Š” ์›๋ž˜ ๊ทธ๋Œ€๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋งํฌ์— ๋Œ€ํ•œ ๋ฆฐํŠธ ๊ทœ์น™์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋‘ ๊ฐœ์˜ ๋ณ„๋„ ์ƒŒ๋“œ๋ฐ•์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ž˜์„œ ํ•˜๋‚˜ํ•˜๋‚˜ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

์–ด๋จธ ๋ฏธ์•ˆํ•ฉ๋‹ˆ๋‹ค! :PI๊ฐ€ ๋‚ด ๊ณ„์ •์˜ ์ƒŒ๋“œ๋ฐ•์Šค ์ˆ˜๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ถ€๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๋‹ค๋ฅธ ๊ฒƒ์„ ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค(๊ทธ๋ฆฌ๊ณ  ์›๋ณธ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋˜๋Œ๋ฆฝ๋‹ˆ๋‹ค).

@gaearon useCallback ์†”๋ฃจ์…˜์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ ๋งํฌ์ž…๋‹ˆ๋‹ค.

๊ดœ์ฐฎ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์ง€๋งŒ ๋ฆฐํ„ฐ๊ฐ€ ๋ถˆํ‰ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์ƒ˜ํ”Œ:

์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค

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

์—ฌ๊ธฐ์˜ ์˜ˆ๋Š” ์•ฝ๊ฐ„ ์ธ์œ„์ ์ž…๋‹ˆ๋‹ค. ๋‚ด ์‹ค์ œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ React๋Š” ํ›จ์”ฌ ๋” ํฐ ์›น ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์ž‘์€ ๋ถ€๋ถ„์ธ DIV์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ „๋‹ฌ๋˜๋Š” ํ•จ์ˆ˜๋Š” Redux ๋ฐ mapDispatchToProps๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง€๋ฉฐ, ์—ฌ๊ธฐ์„œ ์ž‘์—… ์ƒ์„ฑ์€ Id๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์ €์žฅ์†Œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด ajax ์š”์ฒญ์„ ํ•ฉ๋‹ˆ๋‹ค. refreshRequest ์†Œํ’ˆ์€ React.createElement๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์›๋ž˜ ๊ตฌํ˜„์—์„œ๋Š” ํด๋ž˜์Šค ๊ตฌ์„ฑ ์š”์†Œ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

componentDidUpdate (prevProps) { const { getData, someId, refreshRequest} = this.props; if (prevProps.refreshRequest!== this.props.refreshRequest) { getData(someId); } }

ํšจ๊ณผ ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒ˜ํ”Œ์— ์“ฐ์—ฌ์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋ฆฐํ„ฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถˆํ‰ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฝ๊ณ  React Hook useEffect์— 'getData' ๋ฐ 'someId' ์ข…์†์„ฑ์ด ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํฌํ•จํ•˜๊ฑฐ๋‚˜ ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค.

๋ฆฐํ„ฐ๊ฐ€ ์›ํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ˜ํ”Œ useEffect์—์„œ ๋ฒ„ํŠผ ์ค‘ ํ•˜๋‚˜๋ฅผ ํด๋ฆญํ•˜๋ฉด ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒˆ ๋ฐ์ดํ„ฐ ์š”์ฒญ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ๋งŒ ํŠธ๋ฆฌ๊ฑฐ๋˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

์˜๋ฏธ๊ฐ€ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋ถˆ๋ถ„๋ช…ํ•œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ๋” ๋ช…ํ™•ํžˆ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

๋ฐฉ๊ธˆ [email protected] ๋ฅผ ๊ฒŒ์‹œํ–ˆ๋Š”๋ฐ ์ด๋Š” ๋ฒ ์–ด ํ•จ์ˆ˜ ์ข…์†์„ฑ์„ ๊ฐ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ์‹คํ—˜์  ์ง€์›์ด ์žˆ์Šต๋‹ˆ๋‹ค( useCallback ์—†์ด๋Š” ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง€ ์•Š์€ ๊ฒฝํ–ฅ์ด ์žˆ์Œ). ๋‹ค์Œ์€ GIF์ž…๋‹ˆ๋‹ค.

demo

์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์—์„œ ์‹œ๋„ํ•ด ๋ณด๊ณ  ์–ด๋–ค ๋Š๋‚Œ์ธ์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค! (https://github.com/facebook/react/pull/15026์—์„œ ํŠน์ • ํ๋ฆ„์— ๋Œ€ํ•ด ๋Œ“๊ธ€์„ ๋‹ฌ์•„์ฃผ์„ธ์š”.)

๋‚ด์ผ ์ด ์Šค๋ ˆ๋“œ์˜ ์˜ˆ์ œ์—์„œ ์‹œ๋„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„์ง ํ•ด๋ณด์ง€๋Š” ์•Š์•˜์ง€๋งŒ ํ˜ธ์ด์ŠคํŒ…๋„ ๊ฐ€๋Šฅํ•œ์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ๊ทธ ์ž๋ฆฌ์—์„œ ์ƒ๊ฐํ•ด๋‚ธ "์ตœ์†Œ ์˜ˆ"์ผ ๋ฟ์ด๋ฏ€๋กœ ์•„๋ฌด ์“ธ๋ชจ๊ฐ€ ์—†์ง€๋งŒ return ๋ฌธ์„ ๋” ์‰ฝ๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ˜ธ์ด์ŠคํŠธ ์„ ์–ธ์„ ๋งŽ์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

function Component() {
  useEffect(() => {
    handleChange
  }, [handleChange])

  return null

  function handleChange() {}
}

๋ฆฐํ„ฐ์— ๊ด€ํ•œ ํ•œ useEffect ์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜๋„๋ก ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ๊ตฌ์„ฑํ•˜๋Š” ์˜ต์…˜์ด ๊ทœ์น™์— ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, AJAX ํ˜ธ์ถœ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํšจ๊ณผ์— ๋Œ€ํ•ด ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ด๊ฒƒ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด์™€ ๊ฐ™์ด ๋ชจ๋“  exhaustive-deps linting ์ด์ ์„ ์žƒ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

const useAsyncEffect = (fn, ...args) => {
    /* eslint-disable react-hooks/exhaustive-deps */
    useEffect(() => {
        fn();
    }, ...args);
};

ํŽธ์ง‘: ์‹ ๊ฒฝ์“ฐ์ง€ ๋งˆ์„ธ์š”. ๊ทœ์น™์˜ additionalHooks ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๊ฒƒ์ด ์ด๋ฏธ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„,
https://codesandbox.io/s/znnmwxol7l ์˜ ์˜ˆ๊ฐ€

์•„๋ž˜๋Š” ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function App() {
  const [currentTime, setCurrentTime] = React.useState(moment());

  const currentMonth = React.useMemo(
    () => {
      console.log("RUN");
      return currentTime.format("MMMM");
    },
    [currentTime.format("MMMM")] // <= this proplem [currentTime]
  );

  return (
    <div className="App">
      <h1>Current month: {currentMonth}</h1>
      <div>
        <button
          onClick={() => setCurrentTime(currentTime.clone().add(1, "days"))}
        >
          + 1 day
        </button>
      </div>
      <div>{currentTime.toString()}</div>
    </div>
  );
}

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ์–ป๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  const currentMonth = React.useMemo(
    () => {
      console.log("RUN");
      return currentTime.format("MMMM");
    },
    [currentTime] // <= this proplem
  );

currentTime ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค currentMonth ์žฌ๊ณ„์‚ฐ ๋ถˆํ•„์š”

๋˜๋Š” ์–ด๋–ป๊ฒŒ ๋“  ์•„๋ž˜์—์„œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  const currentMonth = React.useMemo(
    () => {
      return currentTime.format("MMMM");
    },
    [myEqualityCheck(currentTime)]
  );

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

@einarq ๋‚ด ์ƒ๊ฐ์—๋Š” on-mount useEffect ๋ชจ๋“  ์ฐธ์กฐ ๊ฐ’์ด ์ ˆ๋Œ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. useMemo ์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ํ›„์—๋Š” ์ด ESlint ๊ทœ์น™์ด ๋ชจ๋“  ์ฐธ์กฐ๋ฅผ ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด(์ž๋™ ์ˆ˜์ • ํฌํ•จ) ์ฝ”๋“œ๋Š” ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

@einarq ์Šค๋ ˆ๋“œ์˜ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด

@nghiepit ๋‹น์‹ ์˜ ์˜ˆ๋Š” ๋‚˜์—๊ฒŒ ์ •๋ง ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅ์ด currentTime.format("MMMM") ์ด๋ฉด useMemo ๋Š” ์ด๋ฏธ ๊ณ„์‚ฐ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ฌด ๊ฒƒ๋„ ์ตœ์ ํ™”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋‘ ๋ฒˆ ๊ณ„์‚ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

additionalHooks ์˜ต์…˜์˜ ์ฝœ๋ฐฑ์ธ ์ธ์ˆ˜ ์ธ๋ฑ์Šค๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ฒซ ๋ฒˆ์งธ https://github.com/facebook/react/blob/9b7e1d1389e080d19e71680bbbe979ec58fa7389/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js# ๊ฐ€ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ง€๊ธˆ ์ฝ”๋“œ์—์„œ ๊ฐ€์ •ํ•˜๊ณ  ์žˆ์Œ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค. L1081

ํ˜„์žฌ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ์ผ๋ฐ˜์ ์ธ ์ง€์นจ์€ ์‚ฌ์šฉ์ž ์ •์˜ Hooks๊ฐ€ deps ์ธ์ˆ˜๋ฅผ ๊ฐ–์ง€ ์•Š๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด deps๊ฐ€ ๊ตฌ์„ฑ๋˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ค์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋Œ€์‹  ์‚ฌ์šฉ์ž์—๊ฒŒ useCallback ๋ฅผ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@CarlosGines OP ๊ฒŒ์‹œ๋ฌผ์—์„œ ์š”์ฒญํ•œ ๋Œ€๋กœ CodeSandbox๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด์œ ๋ฅผ ๋ฌป๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํ™•์ธํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ํŠนํžˆ TypeScript๋กœ ์ž‘์„ฑ๋œ ๊ฒฝ์šฐ.

๋” ์œ ์šฉํ•œ ๋ฉ”์‹œ์ง€์™€ ๋” ๋˜‘๋˜‘ํ•œ ํœด๋ฆฌ์Šคํ‹ฑ์œผ๋กœ [email protected] ๋ฅผ ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๊ฐ€ ์•ˆ์ •ํ™”๋˜๊ธฐ ์ „์— ์‹œ๋„ํ•ด ๋ณด์‹ญ์‹œ์˜ค.

์ด ์Šค๋ ˆ๋“œ์˜ ๋Œ€๋ถ€๋ถ„์˜ ์˜ˆ์ œ์—์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ํ•ฉ๋ฆฌ์ ์ธ ์กฐ์–ธ์„ ์ œ๊ณตํ•  ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

[email protected] ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์˜ˆ.

์‹ค์ œ๋กœ ๋ช‡ ๊ฐ€์ง€ ์ž‘์€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ํฌํ•จ๋œ [email protected] ์„ ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

@gaearon ํ˜น์‹œ eslint ์ด ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค ์•ˆ์—์„œ ์ž‘๋™ํ•˜๊ฒŒ ํ•ด์ฃผ์…จ๋‚˜์š”?

@einarq ์•„๋งˆ๋„ ์ด์™€ ๊ฐ™์€ ๊ฒƒ์ด ์ž‘๋™ํ• ๊นŒ์š”?

const useDidMount = fn => {
  const callbackFn = useCallback(fn)
  useEffect(() => {
    callbackFn()
  }, [callbackFn])
}

๋‚˜๋Š” ์‹ค์ œ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๊ฐ„๋‹จํ•œ CRA ์•ฑ์—์„œ ์ž‘๋™ํ•˜๋„๋ก ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ๋งํ•˜๊ธฐ ๋ถ€๋„๋Ÿฝ์Šต๋‹ˆ๋‹ค( ๋‚ด ์Šค๋‹ˆํŽซ ๊ธฐ๋ฐ˜).
๋‹ค์Œ์€ ์ฝ”๋“œ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ ๋ถ„๊ธฐ ๋œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋ฌธ์„œ ์—์„œ ์ด ๋ฉ”๋ชจ๋ฅผ ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ : Create React App์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ด ๊ทœ์น™์„ ์ง์ ‘ ์ถ”๊ฐ€ํ•˜๋Š” ๋Œ€์‹  ํ•ด๋‹น ๊ทœ์น™์„ ํฌํ•จํ•˜๋Š” react-script์˜ ๋ฆด๋ฆฌ์Šค๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์‹ญ์‹œ์˜ค.

๊ทธ๋Ÿฐ๋ฐ ์ง€๊ธˆ์€ CRA๋กœ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๋‚˜์š”? ๐Ÿ‘‚

๋„ค, ESLint ๊ตฌ์„ฑ์— ์ถ”๊ฐ€ํ•  ๋•Œ๊นŒ์ง€ ๊บผ๋‚ด์„œ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ถ„๊ธฐ์—์„œ ๊บผ๋‚ด๊ณ  ๋ณ‘ํ•ฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. :-)

์•ˆ๋…•ํ•˜์„ธ์š”,

์šฐ์„ : ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ฐ ์ผ๋ฐ˜์ ์œผ๋กœ ํ•˜๊ณ  ์žˆ๋Š” ๋†€๋ผ์šด ์ž‘์—…๊ณผ ๊ธด๋ฐ€ํ•˜๊ฒŒ ํ˜‘๋ ฅํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

Fetch API๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์ถ•ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ํ›„ํฌ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด Codesandbox๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

Codesandbox์˜ ์˜ˆ

https://codesandbox.io/s/kn0km7mzv

์ฐธ๊ณ : ๋ฌธ์ œ(์•„๋ž˜ ์ฐธ์กฐ)๋กœ ์ธํ•ด ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ์‹œ์—ฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” DDoS jsonplaceholder.typicode.com ๋ฅผ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์นด์šดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์š”์ฒญ ์ œํ•œ๊ธฐ๋ฅผ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ฌธ์ œ๋ฅผ ์‹œ์—ฐํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์ด ํ›Œ๋ฅญํ•œ ํ”„๋กœ์ ํŠธ์— ๋ฌด์ œํ•œ์˜ ์š”์ฒญ์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ ์ž˜๋ชป๋˜์—ˆ๋‹ค๊ณ  ๋Š๊ผˆ์Šต๋‹ˆ๋‹ค.

์„ค๋ช…

์•„์ด๋””์–ด๋Š” API ์š”์ฒญ์˜ 3๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ธ ๋กœ๋“œ, ์„ฑ๊ณต ๋ฐ ์˜ค๋ฅ˜๋ฅผ ๋ณด๋‹ค ์‰ฝ๊ฒŒ โ€‹โ€‹์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ isLoading , response ๋ฐ error. It makes sure that either ์‘๋‹ต or ์˜ค๋ฅ˜ is set and updates 3๊ฐœ ์†์„ฑ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ useFetch() ๋ฅผ ๋นŒ๋“œํ–ˆ์Šต๋‹ˆ๋‹ค response is set and updates isLoading . As the name implies, it uses the Fetch` API.

์ด๋ฅผ ์œ„ํ•ด 3๊ฐœ์˜ useState ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  const [isLoading, setIsLoading] = useState(false);
  const [response, setResponse] = useState(null);
  const [error, setError] = useState(null);

useEffect ํ›„ํฌ:

useEffect(
    () => {
      fetch(url, fetchConfig)
        .then(/* Handle fetch response... See Codesandbox for the actual implementation */)
    },
    [url]
  );

๊ทธ๊ฒƒ์€ ์˜ค๋žซ๋™์•ˆ์˜ ์ข…์† ๋ฐฐ์—ด๋กœ๋กœ ๋ฒŒ๊ธˆ์„ ์ž‘๋™ useEffect ๋งŒ ํฌํ•จ [url] . fetchConfig (= [url, fetchConfig] )๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ํŠน์ • ์‚ฌ์šฉ ์‚ฌ๋ก€์˜ ๊ฒฝ์šฐ url ๋ณ€๊ฒฝ๋˜์—ˆ์ง€๋งŒ ๋ฆฐํ„ฐ๊ฐ€ [url] ( v1.4.0 ๋ฐ v1.5.0-beta.1 ).

์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ๊ฐ€ ๋๋‚˜๋ฉด 3๊ฐœ์˜ ์ƒํƒœ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

  return {
    error,
    isLoading,
    response
  };

Linting ์ œ์•ˆ์ด ํƒ€๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ง€์นจ์„ ์š”์ฒญํ•˜๊ธฐ์— ์ ํ•ฉํ•œ ๊ณณ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

fetchConfig ๋ณ€๊ฒฝ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”? ์ •์ ์ผ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๊ดœ์ฐฎ์•„. ์ง€๋‚œ ์ฃผ์˜ ์ˆ˜์ • ์‚ฌํ•ญ ๋ฐ ๊ฐœ์„  ์‚ฌํ•ญ๊ณผ ํ•จ๊ป˜ [email protected] ๋ฅผ ์ถœ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.
์ด ์Šค๋ ˆ๋“œ๋Š” ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ๋‹ค์–‘ํ•œ ํŒจํ„ด์„ ์ฐพ๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ถ„๊ป˜ ์ง„์‹ฌ์œผ๋กœ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. (ํŠนํžˆ ์ƒŒ๋“œ๋ฐ•์Šค๋ฅผ ์ œ๊ณตํ•ด์ฃผ์‹  ๋ถ„๋“ค. :-)


๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ผ์ผ์ด ์ผ์ผ์ด ์ผ์ผ์ด ์ผ์ผ์ด ์ž์„ธํžˆ ๋‹ต๋ณ€๋“œ๋ฆฌ์ง€๋Š” ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค.

๋Œ€์‹ , ์šฐ๋ฆฌ๋Š” ์•ž์œผ๋กœ ๋ฉฐ์น  ์•ˆ์— ์ผ๋ฐ˜์ ์ธ ์กฐ๋ฆฌ๋ฒ•๊ณผ ๋ฌธ์ œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๋ฌธ์„œ์—์„œ ๋งํฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์˜ ๋ชจ๋“  ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ด ํฌํ•จ๋˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค(๋˜๋Š” ๋“œ๋ฌธ ํŒจํ„ด์— ๋Œ€ํ•ด์„œ๋Š” ๋ณ„๋„์˜ ๋ฌธ์ œ์—์„œ ํ›„์† ์กฐ์น˜๋ฅผ ์š”์ฒญํ•˜์‹ญ์‹œ์˜ค).

์˜ˆ์ œ๊ฐ€ ๊ฒŒ์‹œ๋˜๋ฉด ์—ฌ๊ธฐ์— ์ฃผ์„์„ ๋‹ฌ๊ณ  ์˜ฌ๋ฐ”๋ฅธ ์ˆ˜์ •์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ด€๋ จ ๋‹ต๋ณ€/์˜ˆ์ œ์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ CodeSandbox๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“  ์ฃผ์„์„ ํŽธ์ง‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋‹น์‹ ๊ณผ ๋ฏธ๋ž˜์˜ ๋…์ž๋“ค์—๊ฒŒ ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๊ฑด๋ฐฐ!

โค๏ธ

@timkraut ๋Š” deps์— fetchConfig ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๊ณ  ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ฐธ์กฐ๊ฐ€ ์œ ์ง€๋˜๋„๋ก ๋ฉ”๋ชจ๋กœ ๊ฐ์‹ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์˜ˆ: https://codesandbox.io/s/9l015v2x4w


์ด๊ฒƒ์— ๋Œ€ํ•œ ๋‚ด ๋ฌธ์ œ๋Š” ์ด์ œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ›„ํฌ์˜ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค...

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

์˜ˆ์‹œ

https://codesandbox.io/s/40v54jnkyw

์ด ์˜ˆ์—์„œ๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ์ž…๋ ฅ ๊ฐ’์„ ์ž๋™ ์ €์žฅํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์„ค๋ช…

5์ดˆ๋งˆ๋‹ค ์ฝ”๋“œ๋Š” ํ˜„์žฌ ๊ฐ’์„ ์ž๋™ ์ €์žฅํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค(์ง€๊ธˆ์€ ํ™”๋ฉด์— ์ถœ๋ ฅํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋จ). ๋ฆฐํ„ฐ๋Š” ํšจ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋นˆ๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ข…์†์„ฑ ๋ฐฐ์—ด์— ๋ชจ๋“  ์ž…๋ ฅ ๊ฐ’์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  useEffect(
    () => {
      if (autoSaveTick % 5 === 0) {
        setAutosaveValue(
          `${input1Value.value}, ${input2Value.value}, ${input3Value.value}`
        );
      }
    },
    [autoSaveTick]
  );

๋‚ด๊ฐ€ ๋ณด๋Š” ๋Œ€์•ˆ์€ ์ •์˜๋œ useTick ๋ฐ useInterval ํ›„ํฌ์™€ ์œ ์‚ฌํ•œ ๊ตฌํ˜„์„ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ref์— ํ• ๋‹น๋œ ์ฝœ๋ฐฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฐํŠธ ๊ทœ์น™์— ๋งž์ถ”๊ธฐ ์œ„ํ•ด ๋ถˆํ•„์š”ํ•œ ํ•จ์ˆ˜ ์žฌ์ •์˜๋ฅผ ์ผ์œผํ‚ฌ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด์ „ ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ(๋ณ€์ˆ˜ A) ์‹œ ๋‹ค๋ฅธ ๋ณ€์ˆ˜ ๊ฐ’(๋ณ€์ˆ˜ B ๋ฐ ๋ณ€์ˆ˜ C)์„ ์‚ฌ์šฉํ•˜๋Š” ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜(๋ณ€์ˆ˜ A)๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์‹คํ–‰๋˜๋Š” ํšจ๊ณผ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

fetchConfig ๋ณ€๊ฒฝ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”? ์ •์ ์ผ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์ข…์†์„ฑ ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ํŠน์ • ๋น„์ฆˆ๋‹ˆ์Šค ์‚ฌ๋ก€์—์„œ ์ด๊ฒƒ์€ ์ ˆ๋Œ€ ์ผ์–ด๋‚  ์ˆ˜ ์—†์ง€๋งŒ ์–ด์จŒ๋“  ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์— ๋Œ€ํ•œ ๋‚ด ๋ฌธ์ œ๋Š” ์ด์ œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ›„ํฌ์˜ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค...

๊ทธ๊ฒƒ์ด ๋ฐ”๋กœ ์šฐ๋ฆฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฌธ์ œ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค./ ์šฐ๋ฆฌ ๊ตฌํ˜„์—์„œ๋Š” ๋ณธ๋ฌธ์„ ๋” ์‰ฝ๊ฒŒ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ด ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค 2๊ฐœ์˜ useMemo() ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„์ง ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„์ด๋””์–ด๊ฐ€ ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”!

๋นˆ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•  ๋•Œ ๊ทœ์น™์ด ๋ถˆํ‰ํ•˜์ง€ ์•Š๊ณ  ์ข…์†์„ฑ์ด ํ•œ ๋ฒˆ๋งŒ ์žˆ๋Š” useEffect๋ฅผ ์–ด๋–ป๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งํ•˜์‹ญ์‹œ์˜ค.

useEffect(() => { init({ dsn, environment}) }, [])

์ด๊ฒƒ์— ๋Œ€ํ•œ ๋‚ด ๋ฌธ์ œ๋Š” ์ด์ œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ›„ํฌ์˜ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค...

๋‚˜๋Š” ์ด๊ฒƒ์ด ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด๋ผ๊ณ  ๋งํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์˜ API์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด ์–ธ์ œ๋“ ์ง€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ํ•ญ์ƒ ์ •์ ์ด๋ผ๋ฉด Hook ํŒฉํ† ๋ฆฌ์— ๋Œ€ํ•œ ์ธ์ˆ˜๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ createFetch(config) ๋ฐ˜ํ™˜์ด useFetch() . ์ตœ๊ณ  ์ˆ˜์ค€์˜ ๊ณต์žฅ์— ์ „ํ™”ํ•ฉ๋‹ˆ๋‹ค.

์กฐ๊ธˆ ์ด์ƒํ•œ๊ฑด ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์ž‘์—… ์ค‘์ธ useSubscription ๋น„์Šทํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ์ด๋ฏ€๋กœ useMemo ์‹ค์ œ๋กœ ํ•ฉ๋ฒ•์ ์ธ ๋‹ต๋ณ€์ž„์„ ์˜๋ฏธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์‚ฌ๋žŒ๋“ค์€ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์— ์ต์ˆ™ํ•ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ โ€” ์šฐ๋ฆฌ๋Š” ์•ž์œผ๋กœ ์ด๊ฒƒ์— ๋Œ€ํ•ด ๋” ๋งŽ์ด ์‚ดํŽด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ž ์žฌ์ ์œผ๋กœ ๋™์ ์ธ ๊ฐœ์ฒด๋ฅผ ์ •์  ๊ฐœ์ฒด๋กœ ์ทจ๊ธ‰ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

@asylejmani ์ƒ๋‹จ ๊ฒŒ์‹œ๋ฌผ์—์„œ ์š”์ฒญํ•œ ๋Œ€๋กœ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ท€ํ•˜์˜ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๊ทœ์น™์˜ ์š”์ ์€ environment ๋ฐ dsn ๊ฐ€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ฒ„๊ทธ๊ฐ€ ์žˆ๊ฑฐ๋‚˜(ํ•ด๋‹น ๊ฐ’์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—) ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๊ณ ์œ ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์ด ๊ฒฝ์šฐ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ์ฃผ์„์„ ๋ฌด์‹œํ•˜๋Š” ๋ฆฐํŠธ ๊ทœ์น™์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•จ).

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ๋‹น์‹ ์ด ๋ฌด์—‡์„ ๋ฌป๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทœ์น™์€ ์ƒํ™ฉ์ด ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ถˆํ‰ํ•˜๋ฉฐ ๊ทธ ๋ณ€๊ฒฝ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™„์ „ํ•œ ์˜ˆ๊ฐ€ ์—†์œผ๋ฉด ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ์ด์œ ์— ๋Œ€ํ•ด ์Šค์Šค๋กœ ๋‹ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@gaearon ๋” ๋ช…ํ™•ํ•˜์ง€

๋‚˜๋Š” ๋นˆ ๋ฐฐ์—ด์ด ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ธ์ƒ์„ ๋ฐ›์•˜์ง€๋งŒ ๊ทœ์น™์€ ํ•ญ์ƒ ๋ฐฐ์—ด์— ์ข…์†์„ฑ์„ ํฌํ•จํ•˜๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.

@asylejmani componentDidMount ์™€ ๊ฐ™์€ ํด๋ž˜์Šค ๋ผ์ดํ”„ ์‚ฌ์ดํด ๋ฉ”์„œ๋“œ์—์„œ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๊ฒƒ์„ ๊ฒฉ๋ฆฌ๋œ ๋ฉ”์„œ๋“œ๋กœ ์ƒ๊ฐํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ํ๋ฆ„์˜ ์ผ๋ถ€๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
componentDidMount ์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ componentDidUpdate ์—์„œ๋„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ตฌ์„ฑ ์š”์†Œ์— ๋ฒ„๊ทธ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ๊ทœ์น™์ด ์ˆ˜์ •ํ•˜๋ ค๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. ๋งˆ์šดํŠธ๋œ ๊ตฌ์„ฑ ์š”์†Œ, ์†Œํ’ˆ์œผ๋กœ ์ž‘์—… ์ˆ˜ํ–‰
  2. ๊ตฌ์„ฑ ์š”์†Œ ์—…๋ฐ์ดํŠธ(์˜ˆ: prop ๊ฐ’์ด ๋ณ€๊ฒฝ๋จ), ์ƒˆ prop ๊ฐ’์œผ๋กœ ์ž‘์—… ์ˆ˜ํ–‰

1๋ฒˆ์€ componentDidMount / useEffect ๋ณธ๋ฌธ์— ๋…ผ๋ฆฌ๋ฅผ ๋„ฃ๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.
2๋ฒˆ์€ componentDidUpdate / useEffect deps์— ๋…ผ๋ฆฌ๋ฅผ ๋„ฃ๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.

๊ทœ์น™์€ ํ๋ฆ„์˜ ๋‘ ๋ฒˆ์งธ ๋ถ€๋ถ„์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ  ์žˆ๋‹ค๊ณ  ๋ถˆํ‰ํ•ฉ๋‹ˆ๋‹ค.

@gaearon ๋” ๋ช…ํ™•ํ•˜์ง€

๋‚˜๋Š” ๋นˆ ๋ฐฐ์—ด์ด ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ธ์ƒ์„ ๋ฐ›์•˜์ง€๋งŒ ๊ทœ์น™์€ ํ•ญ์ƒ ๋ฐฐ์—ด์— ์ข…์†์„ฑ์„ ํฌํ•จํ•˜๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.

๋‚˜์™€ @asylejmani ๋Š” ์—ฌ๊ธฐ์—์„œ ๊ฐ™์€ ํŽ˜์ด์ง€์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ @gaearon ์ด ๋งํ•˜๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ์ข…์†์„ฑ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋งˆ์šดํŠธ์— ๋Œ€ํ•œ ํšจ๊ณผ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ž˜๋ชป๋œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ •๋‹นํ•œ ๋ง์ž…๋‹ˆ๊นŒ? ๋นˆ ๋ฐฐ์—ด์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์€ "๋‚ด๊ฐ€ ํ•˜๋Š” ์ผ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค"๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ทœ์น™์„ ์œ ์ง€ํ•˜๋ ค๋Š” ์ด์œ ๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„์ง ์ƒŒ๋“œ๋ฐ•์Šค๋ฅผ ์ œ๊ณตํ•˜์ง€ ๋ชปํ•ด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” Create React App ์˜ˆ์ œ๋กœ ๋‹ค๋ฅธ ๋‚  ๋ฐค์„ ์‹œ์ž‘ํ–ˆ๋Š”๋ฐ ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ eslint๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ๊ณ , ๋จผ์ € ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋‹ค์‹œ ๋กœ๋“œํ•  ๋•Œ ์ƒŒ๋“œ๋ฐ•์Šค๋ฅผ ์žƒ์–ด๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค(CodeSandbox ์ž„์‹œ ์ €์žฅ, ๋‚ด ์ž˜๋ชป).
๊ทธ ๋‹ค์Œ ๋‚˜๋Š” ์ž ์ž๋ฆฌ์— ๋“ค์–ด์•ผ ํ–ˆ๊ณ , ๊ทธ ์ดํ›„๋กœ ์‹œ๊ฐ„์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

์–ด์จŒ๋“ , ๋‚˜๋Š” ๋‹น์‹ ์ด ๋งํ•˜๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜๊ณ  ์ •์ƒ์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์ข…์†์„ฑ์„ ํฌํ•จํ•˜๊ณ  ๋งˆ์šดํŠธ์—์„œ๋งŒ ์‹คํ–‰ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

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

@asylejmani ๋Š” https://github.com/facebook/react/issues/14920#issuecomment -466378650๊ณผ ์œ ์‚ฌํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ทœ์น™์ด ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•ด๋‹น ์œ ํ˜•์˜ ์ฝ”๋“œ์— ๋Œ€ํ•ด ์ˆ˜๋™์œผ๋กœ ๋น„ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ์šฐ์—๋Š” ๊ทœ์น™์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์˜๋ฏธ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ๋‚˜์—๊ฒŒ ๋งค์šฐ ์ผ๋ฐ˜์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

useEffect(() => {
    if(!dataIsLoaded) { // flag from redux
        loadMyData(); // redux action creator
    }
}, []);

์ด ๋‘ ์ข…์†์„ฑ์€ ๋ชจ๋‘ redux์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ(์ด ๊ฒฝ์šฐ)๋Š” ํ•œ ๋ฒˆ๋งŒ ๋กœ๋“œ๋˜์–ด์•ผ ํ•˜๋ฉฐ ์ž‘์—… ์ƒ์„ฑ์ž๋Š” ํ•ญ์ƒ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ redux์—๋งŒ ํ•ด๋‹น๋˜๋ฉฐ eslint ๊ทœ์น™์€ ์ด๊ฒƒ์„ ์•Œ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๊ฒฝ๊ณ ํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋นˆ ๋ฐฐ์—ด์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๊ทœ์น™์„ ๋น„ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ์ „ํžˆ ๊ถ๊ธˆํ•˜์‹ญ๋‹ˆ๊นŒ? ์ผ๋ถ€๋งŒ ์ œ๊ณตํ–ˆ์ง€๋งŒ ์ „๋ถ€๋Š” ์•„๋‹Œ ๊ฒฝ์šฐ ๋˜๋Š” ์ „ํ˜€ ์ œ๊ณตํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ˆ„๋ฝ๋œ deps์— ๋Œ€ํ•ด ๊ทœ์น™์ด ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด ๋งˆ์Œ์— ๋“ญ๋‹ˆ๋‹ค. ๋นˆ ๋ฐฐ์—ด์€ ๋‚˜์™€ ๋‹ค๋ฅธ ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ €๋งŒ ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ์–ด์š” :)

๋ชจ๋“  ๋…ธ๋ ฅ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค! ๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž๋กœ์„œ ์šฐ๋ฆฌ์˜ ์‚ถ์„ ๋” ์ข‹๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด :)

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

@einarq ์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๋‚ด๊ฐ€ ๋ช‡ ๋ฒˆ ์‚ฌ์šฉํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "componentDidMount"์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ(redux ๋˜๋Š” ๋ฌด์—‡์ด๋“ ) ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ ์ธ๋ผ์ธ ๊ทœ์น™์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ตœ์„ ์˜ ์„ ํƒ์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๋‹น์‹ ์ดํ•˜๋Š” ์ผ์„ ์ •ํ™•ํžˆ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ๋ชจ๋“  ํ˜ผ๋ž€์€ [] ๋Œ€ [์ผ๋ถ€]์˜€๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๋ฌผ๋ก  ๋ฉ‹์ง„ ์ž‘์—…์— ๋Œ€ํ•ด @gaearon ์—๊ฒŒ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค :)

๋‚˜์™€ @asylejmani ๋Š” ์—ฌ๊ธฐ์—์„œ ๊ฐ™์€ ํŽ˜์ด์ง€์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ @gaearon ์ด ๋งํ•˜๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ์ข…์†์„ฑ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋งˆ์šดํŠธ์— ๋Œ€ํ•œ ํšจ๊ณผ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ž˜๋ชป๋œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ •๋‹นํ•œ ๋ง์ž…๋‹ˆ๊นŒ?

์˜ˆ. ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์†Œํ’ˆ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. useEffect ์˜ ๋””์ž์ธ์€ ๋‹น์‹ ์ด ๊ทธ๊ฒƒ์— ์ง๋ฉดํ•˜๋„๋ก ๊ฐ•์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์œ ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์˜๊ฒฌ์€ ์ž˜ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค: https://github.com/facebook/react/issues/14920#issuecomment -470913287.

์ด ๋‘ ์ข…์†์„ฑ์€ ๋ชจ๋‘ redux์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ(์ด ๊ฒฝ์šฐ)๋Š” ํ•œ ๋ฒˆ๋งŒ ๋กœ๋“œ๋˜์–ด์•ผ ํ•˜๋ฉฐ ์ž‘์—… ์ƒ์„ฑ์ž๋Š” ํ•ญ์ƒ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๋™์ผํ•œ ๊ฒฝ์šฐ ์ข…์†์„ฑ์— ํฌํ•จํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๊ฐ•์กฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค โ€” ๋‹น์‹ ์˜ ์˜์กด์„ฑ์ด ๊ฒฐ์ฝ” ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ™•์‹ ํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ๋“ค์„ ๋‚˜์—ดํ•˜๋Š” ๋ฐ ์•„๋ฌด๋Ÿฐ ํ•ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค . ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜์ค‘์— ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ(์˜ˆ: ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ) ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋นˆ ๋ฐฐ์—ด์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๊ทœ์น™์„ ๋น„ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ์ „ํžˆ ๊ถ๊ธˆํ•˜์‹ญ๋‹ˆ๊นŒ?

์•„๋‹ˆ์š”. ๋นˆ ๋ฐฐ์—ด์„ ์ œ๊ณตํ•œ ๋‹ค์Œ ์ผ๋ถ€ props ๋˜๋Š” state๊ฐ€ ์˜ค๋ž˜๋œ ์ด์œ ๋ฅผ ๊ถ๊ธˆํ•ดํ•˜๋Š” ๊ฒƒ์€ ๋ง ๊ทธ๋Œ€๋กœ ๊ฐ€์žฅ ํ”ํ•œ ์‹ค์ˆ˜์ž…๋‹ˆ๋‹ค.

>

์˜๋ฏธ๊ฐ€ ํฝ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

2019๋…„ 3์›” 8์ผ 15:27์— Dan Abramov [email protected]์ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

๋‚˜์™€ @asylejmani ๋Š” ์—ฌ๊ธฐ์—์„œ ๊ฐ™์€ ํŽ˜์ด์ง€์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ @gaearon ์ด ๋งํ•˜๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ์ข…์†์„ฑ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋งˆ์šดํŠธ์— ๋Œ€ํ•œ ํšจ๊ณผ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ž˜๋ชป๋œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ •๋‹นํ•œ ๋ง์ž…๋‹ˆ๊นŒ?

์˜ˆ. ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์†Œํ’ˆ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. useEffect์˜ ๋””์ž์ธ์€ ๋‹น์‹ ์ด ๊ทธ๊ฒƒ์— ์ง๋ฉดํ•˜๋„๋ก ๊ฐ•์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์œ ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ฃผ์„์€ ๊ทธ๊ฒƒ์„ ์ž˜ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค: #14920 (comment).

์ด ๋‘ ์ข…์†์„ฑ์€ ๋ชจ๋‘ redux์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ(์ด ๊ฒฝ์šฐ)๋Š” ํ•œ ๋ฒˆ๋งŒ ๋กœ๋“œ๋˜์–ด์•ผ ํ•˜๋ฉฐ ์ž‘์—… ์ƒ์„ฑ์ž๋Š” ํ•ญ์ƒ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๋™์ผํ•œ ๊ฒฝ์šฐ ์ข…์†์„ฑ์— ํฌํ•จํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๊ฐ•์กฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค โ€” ๋‹น์‹ ์˜ ์˜์กด์„ฑ์ด ๊ฒฐ์ฝ” ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ™•์‹ ํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ๋“ค์„ ๋‚˜์—ดํ•˜๋Š” ๋ฐ ์•„๋ฌด๋Ÿฐ ํ•ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜์ค‘์— ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ(์˜ˆ: ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ) ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋นˆ ๋ฐฐ์—ด์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๊ทœ์น™์„ ๋น„ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ์ „ํžˆ ๊ถ๊ธˆํ•˜์‹ญ๋‹ˆ๊นŒ?

์•„๋‹ˆ์š”. ๋นˆ ๋ฐฐ์—ด์„ ์ œ๊ณตํ•œ ๋‹ค์Œ ์ผ๋ถ€ props ๋˜๋Š” state๊ฐ€ ์˜ค๋ž˜๋œ ์ด์œ ๋ฅผ ๊ถ๊ธˆํ•ดํ•˜๋Š” ๊ฒƒ์€ ๋ง ๊ทธ๋Œ€๋กœ ๊ฐ€์žฅ ํ”ํ•œ ์‹ค์ˆ˜์ž…๋‹ˆ๋‹ค.

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ๋ณด๊ฑฐ๋‚˜ ์Šค๋ ˆ๋“œ๋ฅผ ์Œ์†Œ๊ฑฐํ•˜์„ธ์š”.

@ํ”ผ๊ณคํ•œ

๊ทธ๋Ÿฌ๋ฉด ์‹ค์ œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ปค๋ฐ‹๋˜๊ธฐ ์ „์— ๋ถ€์ž‘์šฉ์ด ๋ฐœ์ƒํ•˜์—ฌ ์›ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ์ž์ฃผ ๋ถ€์ž‘์šฉ์ด ํŠธ๋ฆฌ๊ฑฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒŒ ๋ฌด์Šจ ๋œป์ธ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์šฐ๋ฆฌ๋Š” ์˜ค๋Š˜ @threepointone ์œผ๋กœ

Lint ๊ทœ์น™์—์„œ ์ˆ˜์ •๋จ

๊ด€๋ จ ์—†๋Š” useEffect ์ข…์†์„ฑ

์ด ๊ทœ์น™์€ ํ•ฉ๋ฒ•์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋” ์ด์ƒ "์™ธ๋ถ€" dep๋ฅผ useEffect ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ๊ตฌ์„ฑ ์š”์†Œ์— ์žˆ์ง€๋งŒ ํšจ๊ณผ ์™ธ๋ถ€์—์„œ ์ •์˜๋œ ๊ธฐ๋Šฅ

Linter๋Š” ์ง€๊ธˆ ์•ˆ์ „ํ•œ ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ๊ฒฝ๊ณ ํ•˜์ง€ ์•Š์ง€๋งŒ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ์šฐ์—๋Š” ๋” ๋‚˜์€ ์ œ์•ˆ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ํšจ๊ณผ ๋‚ด์—์„œ ํ•จ์ˆ˜๋ฅผ ์ด๋™ํ•˜๊ฑฐ๋‚˜ useCallback ๋ž˜ํ•‘).

์‚ฌ์šฉ์ž ์ฝ”๋“œ์—์„œ ์ˆ˜์ •ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Œ

props ๋ณ€๊ฒฝ ์‹œ ์ƒํƒœ ์žฌ์„ค์ •

์ด๊ฒƒ์€ ๋” ์ด์ƒ ๋ฆฐํŠธ ์œ„๋ฐ˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์ง€๋งŒ props์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ์ƒํƒœ๋ฅผ ์žฌ์„ค์ •ํ•˜๋Š” ๊ด€์šฉ์  ๋ฐฉ๋ฒ•์€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค . ์ด ์†”๋ฃจ์…˜์—๋Š” ์ผ๊ด€์„ฑ ์—†๋Š” ๋ Œ๋”๋ง์ด ์ถ”๊ฐ€๋กœ ํฌํ•จ๋˜๋ฏ€๋กœ ๋ฐ”๋žŒ์งํ•œ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

"๋‚ด ๋น„ ๊ธฐ๋Šฅ ๊ฐ’์€ ์ผ์ •ํ•ฉ๋‹ˆ๋‹ค"

ํ›„ํฌ๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ์ •ํ™•ํ•จ์„ ์ถ”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์ด (๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ๋Š” ์ƒ๋žต ํ•  ์ˆ˜ ์žˆ์Œ) deps๋ฅผ ์ง€์ •ํ•˜๋ฉด, ์šฐ๋ฆฌ๋Š” ๊ฐ•ํ•˜๊ฒŒ ๋‹น์‹ ์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ์ƒ๊ฐ๋„ ์‚ฌ๋žŒ์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์˜ˆ, ์ด useDebounce ์˜ˆ์—์„œ๋Š” ์ง€์—ฐ์ด ๋ณ€๊ฒฝ ๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—ฌ์ „ํžˆ ๋ฒ„๊ทธ์ด์ง€๋งŒ Hook์€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹ค๋ฅธ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋„ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. (์˜ˆ: Hooks๋Š” ๋ชจ๋“  ๊ฐ’์ด ๋™์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ซ ๋ฆฌ๋กœ๋”ฉ๊ณผ ํ›จ์”ฌ ๋” ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค.)

ํŠน์ • ๊ฐ’์ด ์ •์ ์ด๋ผ๊ณ  ์ ˆ๋Œ€์ ์œผ๋กœ ์ฃผ์žฅํ•œ๋‹ค๋ฉด ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฐ€์žฅ ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์€ API์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

const useFetch = createFetch({ /* config object */});
const useDebounce = createDebounce(500);
const FormInput = createInput({ rules: [emailValidator, phoneValidator] });

๊ทธ๋Ÿฐ ๋‹ค์Œ render ์•ˆ์— ๋„ฃ์ง€ ์•Š๋Š” ํ•œ ๋ถ„๋ช…ํžˆ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (์ด๊ฒƒ์€ Hook์˜ ๊ด€์šฉ์  ์‚ฌ์šฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค.) ํ•˜์ง€๋งŒ <Slider min={50} /> can never change ๋ผ๋Š” ๋ง์€ ์‹ค์ œ๋กœ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ๋ˆ„๊ตฐ๊ฐ€ ๊ทธ๊ฒƒ์„ <Slider min={state ? 50 : 100} /> ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋ˆ„๊ตฐ๊ฐ€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let slider
if (isCelsius) {
  slider = <Slider min={0} max={100} />
} else {
  slider = <Slider min={32} max={212} />
}

๋ˆ„๊ตฐ๊ฐ€ isCelsius ์ƒํƒœ๋ฅผ ์ „ํ™˜ํ•˜๋ฉด min ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ Slider ๊ฐ€ ๋™์ผํ•œ์ง€ ์—ฌ๋ถ€๋Š” ๋ถ„๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ํŠธ๋ฆฌ์—์„œ ๋™์ผํ•œ ์œ„์น˜์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค). ๋”ฐ๋ผ์„œ ์ด๊ฒƒ์€ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ธก๋ฉด์—์„œ ์ค‘์š”ํ•œ ๋ฐœํŒ์ž…๋‹ˆ๋‹ค. React์˜ ์ฃผ์š” ํฌ์ธํŠธ๋Š” ์—…๋ฐ์ดํŠธ๊ฐ€ ์ดˆ๊ธฐ ์ƒํƒœ์ฒ˜๋Ÿผ ๋ Œ๋”๋ง๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋ณดํ†ต ์–ด๋Š ๊ฒƒ์ด ์–ด๋Š ์ƒํƒœ์ธ์ง€ ์•Œ ์ˆ˜ ์—†์Œ). prop ๊ฐ’ B๋ฅผ ๋ Œ๋”๋งํ•˜๋“  prop ๊ฐ’ A์—์„œ B๋กœ ์ด๋™ํ•˜๋“  ์ƒ๊ด€์—†์ด ๋™์ผํ•˜๊ฒŒ ๋ณด์ด๊ณ  ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š์ง€๋งŒ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ์ ์šฉ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ ๊ฒฝ๊ณ ํ•˜๋Š”(๊ทธ๋Ÿฌ๋‚˜ ์ฒซ ๋ฒˆ์งธ ๊ฐ’์„ ์ œ๊ณตํ•˜๋Š”) ํ›„ํฌ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์–ด๋„ ๊ทธ๋•Œ๋Š” ์ฃผ๋ชฉ๋ฐ›์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋” ํฝ๋‹ˆ๋‹ค.

function useMyHook(a) {
  const initialA = usePossiblyStaleValue(a);
  // ...
}

function usePossiblyStaleValue(value) {
  const ref = useRef(value);

  if (process.env.NODE_ENV !== 'production') {
    if (ref.current !== value) { // Or your custom comparison logic
      console.error(
        'Unlike normally in React, it is not supported ' +
        'to pass dynamic values to useMyHook(). Sorry!'
      );
    }
  }

  return ref.current;
}

์—…๋ฐ์ดํŠธ๋ฅผ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์—†๋Š” ํ•ฉ๋ฒ•์ ์ธ ๊ฒฝ์šฐ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด jQuery ํ”Œ๋Ÿฌ๊ทธ์ธ์ด๋‚˜ DOM API์™€ ๊ฐ™์ด ํ•˜์œ„ ์ˆ˜์ค€ API๊ฐ€ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์†Œ๋น„์ž๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฒฝ๊ณ ๊ฐ€ ์—ฌ์ „ํžˆ ์ ์ ˆํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์—…๋ฐ์ดํŠธ์—์„œ key ๋ฅผ ์žฌ์„ค์ •ํ•˜๋Š” ๋ž˜ํผ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šฌ๋ผ์ด๋”๋‚˜ ์ฒดํฌ๋ฐ•์Šค์™€ ๊ฐ™์€ ๋ฆฌํ”„ ๊ตฌ์„ฑ์š”์†Œ์— ๋” ์ ํ•ฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

"๋‚ด ๊ธฐ๋Šฅ ๊ฐ’์€ ์ผ์ •ํ•ฉ๋‹ˆ๋‹ค"

์šฐ์„ , ๊ทธ๊ฒƒ์ด ์ผ์ •ํ•˜๊ณ  ์ตœ์ƒ์œ„ ๋ฒ”์œ„๋กœ ํ˜ธ์ด์ŠคํŠธ๋˜๋ฉด ๋ฆฐํ„ฐ๋Š” ๋ถˆํ‰ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์€ ์†Œํ’ˆ์ด๋‚˜ ์ปจํ…์ŠคํŠธ์—์„œ ์˜ค๋Š” ๊ฒƒ์—๋Š” ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ์ง„์ • ์œผ๋กœ ์ผ์ •ํ•˜๋‹ค๋ฉด deps๋กœ ์ง€์ •ํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ Hook ๋‚ด๋ถ€์˜ setState ํ•จ์ˆ˜๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ฐ˜ํ™˜๋œ ๋‹ค์Œ ํšจ๊ณผ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์ด. Lint ๊ทœ์น™์€ ์ด์™€ ๊ฐ™์€ ๊ฐ„์ ‘ ์ฐธ์กฐ๋ฅผ ์ดํ•ดํ•  ๋งŒํผ ๋˜‘๋˜‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ํ•œํŽธ์œผ๋กœ ๋ˆ„๊ตฌ๋“ ์ง€ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์— ๋‚˜์ค‘์— ํ•ด๋‹น ์ฝœ๋ฐฑ์„ ๋ž˜ํ•‘ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ทธ ์•ˆ์— ์žˆ๋Š” ๋‹ค๋ฅธ prop ๋˜๋Š” state๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ผ์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค! ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋ฉด ๋ถˆ์พŒํ•œ prop/state ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค.

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

์ด๊ฒƒ์˜ ๋ฐ˜๋Œ€ ์ŠคํŽ™ํŠธ๋Ÿผ์—๋Š” ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(ํ•จ์ˆ˜ ๊ฐ’์€ ํ•ญ์ƒ ๋ณ€๊ฒฝ๋จ). ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ(๋™์ผํ•œ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ) ์ด์ œ Lint ๊ทœ์น™์—์„œ ์ด๋ฅผ ํฌ์ฐฉํ•˜๊ณ  ์ˆ˜์ • ์‚ฌํ•ญ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ช‡ ๋‹จ๊ณ„ ์•„๋ž˜๋กœ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ†ต๊ณผํ•˜๋ฉด ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค.

์—ฌ์ „ํžˆ useCallback ๋กœ ๊ฐ์‹ธ์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์  ์œผ๋กœ ํ•จ์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์€ ์œ ํšจํ•˜๋ฉฐ ๋ฒ„๊ทธ์˜ ์œ„ํ—˜ ์—†์ด ์ด ๊ฒฝ์šฐ๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. onChange={shouldHandle ? handleChange : null} ๋˜๋Š” ๊ฐ™์€ ์œ„์น˜์—์„œ foo ? <Page fetch={fetchComments /> : <Page fetch={fetchArticles /> ๋ Œ๋”๋ง ๋“ฑ. ๋˜๋Š” ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ ์ƒํƒœ๋ฅผ ๋‹ซ๋Š” fetchComments ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ž‘์ด ์ž๋™์œผ๋กœ ๋ณ€๊ฒฝ๋˜์ง€๋งŒ ํ•จ์ˆ˜ ์ฐธ์กฐ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž๋…€๋Š” ํ•ด๋‹น ์—…๋ฐ์ดํŠธ๋ฅผ ๋†“์น  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž๋…€์—๊ฒŒ ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ ์™ธ์—๋Š” ์˜ต์…˜์ด ์—†์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ useCallback ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ID ์ž์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Š” ์œ ์šฉํ•œ ์†์„ฑ์ด๋ฉฐ ํ”ผํ•ด์•ผ ํ•  ์žฅ์• ๋ฌผ์ด ์•„๋‹™๋‹ˆ๋‹ค.

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

useWarnAboutTooFrequentChanges([deps]);

์ด๊ฒƒ์€ ์ด์ƒ์ ์ด์ง€ ์•Š์œผ๋ฉฐ ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ ๋” ์šฐ์•„ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ข‹์•„ํ•˜๋Š” ๊ฒฝ์šฐ ๋™์˜ ์ด ๊ฝค ๋ถˆ์พŒํ•œ์ž…๋‹ˆ๋‹ค. ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์€ rules ์ •์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜ˆ: API๋ฅผ createTextInput(rules) ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  register ๋ฐ unregister ์„ useCallback . ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์€ register ๋ฐ unregister ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  dispatch ๋งŒ ๋„ฃ๋Š” ๋ณ„๋„์˜ ์ปจํ…์ŠคํŠธ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ฝ๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ ID๋ฅผ ๊ฐ–์ง€ ์•Š์„ ๊ฒƒ์ž„์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

ํ•จ์ˆ˜ ์ข…์†์„ฑ์„ ์™„์ „ํžˆ ๋ฌด์‹œํ•˜๋ฉด ํ•จ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ Hooks์—์„œ ๋” ๋‚˜์œ ๋ฒ„๊ทธ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ณ„์† ์˜ค๋ž˜๋œ props์™€ state๊ฐ€ ํ‘œ์‹œ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๋ณตํ•ฉ ๊ฐ€์น˜ ๋ณ€ํ™”์— ๋Œ€์‘ํ•˜๊ธฐ

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

์ฆ‰, fullName ๋ฅผ setSubmittedData({firstName, lastName}) ๋Œ€์‹  [submittedData] ๋กœ ๋งŒ๋“ค๊ณ  firstName ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ข…์†์„ฑ์„ ํ†ตํ•ด ์‹œ๋„ํ•œ ์ž‘์—…์„ ๊ณ„์† ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค lastName .

ํ•„์ˆ˜/๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์™€ ํ†ตํ•ฉ

jQuery ํ”Œ๋Ÿฌ๊ทธ์ธ ๋˜๋Š” ์›์‹œ DOM API์™€ ๊ฐ™์€ ํ•„์ˆ˜ ํ•ญ๋ชฉ๊ณผ ํ†ตํ•ฉํ•  ๋•Œ ์•ฝ๊ฐ„์˜ ๋ถˆํŽธํ•จ์ด ์˜ˆ์ƒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ์˜ˆ์ œ์—์„œ ํšจ๊ณผ ๋ฅผ ์ข€ ๋” ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.


์•„๋ฌด๋„ ์žŠ์ง€ ์•Š์•˜์œผ๋ฉด ์ข‹๊ฒ ์–ด! ๋‚ด๊ฐ€ ํ•œ ๊ฒฝ์šฐ ๋˜๋Š” ๋ญ”๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ์šฐ๋ฆฌ๋Š” ๊ณง ์ด๊ฒƒ์˜ ๊ตํ›ˆ์„ ์ผ๋ถ€ ๋ฌธ์„œ๋กœ ๋ฐ”๊พธ๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@gaearon , ์‹œ๊ฐ„์„ ๋‚ด์–ด ๋ฌธ์ œ๋ฅผ (@trevorgithub์˜ #14920(๋Œ“๊ธ€))์„ ๋†“์ณค์Šต๋‹ˆ๋‹ค . (๋งŽ์€ ๋ถ„๋“ค์ด ํ”ผ๋“œ๋ฐฑ์„ ๋งŽ์ด ์ฃผ์…”์„œ ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ œ ์›๋ž˜ ๋Œ“๊ธ€์ด ์ด์Šˆ ๋Œ“๊ธ€ ์ค‘๊ฐ„์— ์ˆจ๊ฒจ์ง„ ํ•ญ๋ชฉ ์„น์…˜์—์„œ ์‚ฌ๋ผ์ง„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.)

๋‚ด ์ƒ˜ํ”Œ์ด 'ํ•„์ˆ˜/๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์™€ ํ†ตํ•ฉ'์— ์†ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๋ฒ”์ฃผ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๊นŒ?

'Imperative/Legacy Code์™€ ํ†ตํ•ฉ' ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ด ๋งŽ์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌํ•œ ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ์ด ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•˜๊ฒ ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ์ถ”์ธกํ•œ๋‹ค:
// eslint-disable-line react-hooks/exhaustive-deps

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

props๋ฅผ ํ†ตํ•ด ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•˜์ง€๋งŒ ๋ช…์‹œ์ ์ธ ๋ณ€๊ฒฝ์ด ์žˆ์„ ๋•Œ๊นŒ์ง€ ํ•ด๋‹น props๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด ํŒŒ์ƒ๋œ ์ƒํƒœ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ๋ชจ๋ธ๋ง ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

"๋‹ค๋ฅธ prop์ด ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ prop์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ์„ ๋ฌด์‹œํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค"๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ "๋‚ด ๊ตฌ์„ฑ ์š”์†Œ์—๋Š” ์ƒํƒœ์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์†Œํ’ˆ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์†Œํ’ˆ์—์„œ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค.โ€

์ผ๋ฐ˜์ ์œผ๋กœ ํŒŒ์ƒ๋œ ์ƒํƒœ๋Š” ๊ถŒ์žฅ๋˜์ง€ ์•Š์ง€๋งŒ ์—ฌ๊ธฐ์„œ๋Š” ์›ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const [currentGetData, setCurrentGetData] = useState(getData);
const [prevRefreshRequest, setPrevRefreshRequest] = useState(refreshRequest);

if (prevRefreshRequest !== refreshRequest) {
  setPrevRefreshRequest(refreshRequest);
  setCurrentGetData(getData);
}

useEffect(() => {
  currentGetData(someId);
}, [currentGetData, someId]);

๋˜ํ•œ ๋‘˜ ํ•„์š”๊ฐ€ ๊ฑฐ๋ผ๊ณ  useCallback ์•ฝ getData ๋‹น์‹ ์ด ์•„๋ž˜๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์œ„ํ•ด ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ํŒจํ„ด์€ ๋‚˜์—๊ฒŒ ๊ทธ๋Š˜์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ๊ฒฝ์šฐ Redux๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ถ€๋ชจ ๊ตฌ์„ฑ ์š”์†Œ์— ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋œ ๊ฒฝ์šฐ ๊ฒฝ์Ÿ ์กฐ๊ฑด์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์˜์‹ฌ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ํšจ๊ณผ์— ์ •๋ฆฌ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋ฅธ ID๋ฅผ ์„ ํƒํ•  ๋•Œ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์š”์ฒญ์ด ์ˆœ์„œ๋Œ€๋กœ ๋„์ฐฉํ•˜์ง€ ์•Š๊ณ  ์ž˜๋ชป๋œ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ๊ฒƒ์€ ๋ช…์‹ฌํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ ์ž์ฒด์— ์žˆ๋Š” ๊ฒฝ์šฐ ์‘๋‹ต์—์„œ setState๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด "๋ฌด์‹œ" ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ•˜๋Š” ํšจ๊ณผ ์ •๋ฆฌ ๊ธฐ๋Šฅ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๋ฌผ๋ก  ๋ฐ์ดํ„ฐ๋ฅผ ์™ธ๋ถ€ ์บ์‹œ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์ธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. Suspense๋„ ๊ทธ๋ ‡๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.)

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ๋™์ผํ•œ "๋กœ๊ทธ"(์–‘์‹ ์ œ์ถœ์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •)๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ ํ•ฉํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

@gaearon ๋‚ด๊ฐ€ ๋ณผ ์ˆ˜์žˆ๋Š” ๋ฌธ์ œ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์—…๋ฐ์ดํŠธ๊ฐ€ ์ปค๋ฐ‹๋˜๊ธฐ ์ „์— ๋ถ€์ž‘์šฉ์ด ๋ฐœ์ƒํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ์ด๋ฒคํŠธ์˜ ๊ฒฐ๊ณผ๋กœ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋‹ค์‹œ ๋ Œ๋”๋ง๋œ๋‹ค๋Š” ์—„๊ฒฉํ•œ ๋ณด์žฅ์ด ์—†์œผ๋ฏ€๋กœ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๊ธฐ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ์‹œ๊ธฐ์ƒ์กฐ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ ๊ฒ€์ƒ‰์–ด๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ œ์ถœํ–ˆ์œผ๋ฉฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ๋กํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น ๋กœ๊ทธ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ๋ถ€์ž‘์šฉ์ด ๋น„๋™๊ธฐ์‹์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ useEffect ์‚ฌ์šฉํ•˜๋ฉด ์ •๋ฆฌ ๊ธฐ๋Šฅ์ด ์ œ๊ณต๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

useReducer ์˜ ๋ฌธ์ œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ธฐ๋กํ•˜๋ ค๋Š” ๊ฐ’์€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ด๋ฏธ ์—ฌ๋Ÿฌ๋ถ„์˜ ๋ ˆ์ด๋”์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค ๐Ÿ™‚

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ๊ถŒ์žฅํ•˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ์ถฉ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์ƒํƒœ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐœ๋ณ„ ๊ฐ’์— ๊ณ„์† ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•์‹์œผ๋กœ ๊ตฌ์„ฑ ์ƒํƒœ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ•จ์ˆ˜๋ฅผ ๋ž˜ํ•‘ํ•˜๊ณ  ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ํŽธ๋ฆฌํ•œ ํ›„ํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

function useBoundCallback(fn, ...bound) {
  return useCallback((...args) => fn(...bound, ...args), [fn, ...bound]);
}

(๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ๋Š” ์กฐ๊ธˆ ๋” ๋ณต์žกํ•˜์ง€๋งŒ ์œ„์˜ ๋‚ด์šฉ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹๊ด€๋ จ ๋ฌธ์ œ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.)

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

์ด ํ๋ฆ„์˜ ๊ฐ„๋‹จํ•œ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. https://codesandbox.io/s/vvv36834k5 ("์ด๋™!"์„ ํด๋ฆญํ•˜๋ฉด ๊ตฌ์„ฑ ์š”์†Œ ๊ฒฝ๋กœ๊ฐ€ ํฌํ•จ๋œ ์ฝ˜์†” ๋กœ๊ทธ๊ฐ€ ํ‘œ์‹œ๋จ)


๋ฌธ์ œ๋Š” ์ด ๊ทœ์น™์—์„œ 2๊ฐœ์˜ ๋ฆฐํ„ฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

React Hook(X)์— ๋ˆ„๋ฝ๋œ ์ข…์†์„ฑ: 'bound'๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํฌํ•จํ•˜๊ฑฐ๋‚˜ ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค.

React Hook(X)์—๋Š” ์ข…์†์„ฑ ๋ฐฐ์—ด์— ์Šคํ”„๋ ˆ๋“œ ์š”์†Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์˜ฌ๋ฐ”๋ฅธ ์ข…์†์„ฑ์„ ์ „๋‹ฌํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ •์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

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


์ƒ๊ฐ:

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

์•ˆ๋…•ํ•˜์„ธ์š” @gaearon , ๋ฐฉ๊ธˆ ์ด ๊ฒฝ๊ณ ๋ฅผ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

Accessing 'myRef.current' during the effect cleanup will likely read a different ref value because by this time React has already updated the ref. If this ref is managed by React, store 'myRef.current' in a variable inside the effect itself and refer to that variable from the cleanup function.

์ด ๋ฉ”์‹œ์ง€๊ฐ€ ์•ฝ๊ฐ„ ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ์ •๋ฆฌ ์‹œ์˜ ref ํ˜„์žฌ ๊ฐ’์ด ํšจ๊ณผ ๋ณธ๋ฌธ์˜ ๊ฐ’๊ณผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ์„ ๊ฒฝ๊ณ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅธ์ชฝ?
๊ทธ๋ ‡๋‹ค๋ฉด ์ด ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•ฉ๋‹ˆ๊นŒ/ํ•ฉ๋ฒ•์ ์ž…๋‹ˆ๊นŒ?

๋‚ด ๊ฒฝ์šฐ, ํฅ๋ฏธ๋กœ์šด ๊ฒฝ์šฐ: CodeSandbox
์ปจํ…์ŠคํŠธ: ์ผ๋ถ€ ์‚ฌ์šฉ์ž ์ง€์ • ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ํ›„ํฌ. ๋‚˜๋Š” ๊ฒฝ์Ÿ ์กฐ๊ฑด๊ณผ ๋งˆ์šดํŠธ๋˜์ง€ ์•Š์€ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ชจ๋‘ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ref์—์„œ ์นด์šดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ref ์ฝ๊ธฐ๋ฅผ ์ˆจ๊ธฐ๊ฑฐ๋‚˜ ์ •๋ฆฌ ์ผ€์ด์Šค์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ๋ถ€์šธ ์ฐธ์กฐ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ด ๊ฒฝ๊ณ ๋ฅผ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์žฅํ™ฉํ•ฉ๋‹ˆ๋‹ค.

@ํ”ผ๊ณคํ•œ

์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ ๊ฒ€์ƒ‰์–ด๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ œ์ถœํ–ˆ์œผ๋ฉฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ๋กํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น ๋กœ๊ทธ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ํ‹ˆ์ƒˆ ์‚ฌ์šฉ ์‚ฌ๋ก€์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด "๋ถ€์ž‘์šฉ"์„ ์›ํ•  ๋•Œ ์ œ์ถœ๋œ ์–‘์‹์„ ๋ดค๋‹ค๋Š” ์‚ฌ์‹ค์ด ์•„๋‹ˆ๋ผ ์–‘์‹ ์ œ์ถœ ์ž์ฒด๋ฅผ ์˜๋ฏธํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋‚ด๊ฐ€ ์ œ๊ณตํ•œ ์†”๋ฃจ์…˜์ด ๊ดœ์ฐฎ์•„ ๋ณด์ž…๋‹ˆ๋‹ค.

@davidje13

๋‘ ๋ฒˆ์งธ๋„ ์ ์šฉ๋  ๋•Œ ์ฒซ ๋ฒˆ์งธ ์˜ค๋ฅ˜๋ฅผ ๋ณด์—ฌ์ค„ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๋ฆฐํŠธ ๊ทœ์น™ ๋ณ€๊ฒฝ ์ œ์•ˆ์— ๋Œ€ํ•œ ์ƒˆ ๋ฌธ์ œ๋ฅผ ์ œ์ถœํ•˜์„ธ์š”.

ํŠนํžˆ ์Šคํ”„๋ ˆ๋“œ ์—ฐ์‚ฐ์ž๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ์žฅ์†Œ์— ๋Œ€ํ•ด ์ด ๊ทœ์น™์„ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ž์‹ ์ด ํ•˜๋Š” ์ผ์„ ์•ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์–ธ์ œ๋“ ์ง€ // eslint-disable-next-line react-hooks/exhaustive-deps ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ณ€์ˆ˜์˜ ์œ ์ผํ•œ ์‚ฌ์šฉ์ด ์Šคํ”„๋ ˆ๋“œ ์—ฐ์‚ฐ์ž์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ์ข…์†์„ฑ์—์„œ ์Šคํ”„๋ ˆ๋“œ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•˜๊ณ  ๊ทœ์น™์ด ์ด๋ฏธ ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํ™•์‹คํžˆ ํ—ˆ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ƒˆ ๋ฌธ์ œ๋ฅผ ์ œ์ถœํ•˜์‹ญ์‹œ์˜ค pls.

@CarlosGines

์ด ๋ฉ”์‹œ์ง€๊ฐ€ ์•ฝ๊ฐ„ ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ์ •๋ฆฌ ์‹œ์˜ ref ํ˜„์žฌ ๊ฐ’์ด ํšจ๊ณผ ๋ณธ๋ฌธ์˜ ๊ฐ’๊ณผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ์„ ๊ฒฝ๊ณ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅธ์ชฝ?

์˜ˆ.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•ฉ๋‹ˆ๊นŒ/ํ•ฉ๋ฒ•์ ์ž…๋‹ˆ๊นŒ?

์Œ .. ๋ฒ„๊ทธ๋กœ ์ด์–ด์ง€๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๐Ÿ™‚

์ปจํ…์ŠคํŠธ: ์ผ๋ถ€ ์‚ฌ์šฉ์ž ์ง€์ • ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ํ›„ํฌ. ๋‚˜๋Š” ๊ฒฝ์Ÿ ์กฐ๊ฑด๊ณผ ๋งˆ์šดํŠธ๋˜์ง€ ์•Š์€ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ชจ๋‘ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ref์—์„œ ์นด์šดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ์•„๋งˆ๋„ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ํ•ฉ๋ฒ•์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Pls๋ฅผ ๋…ผ์˜ํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ๋ฌธ์ œ๋ฅผ ์ œ์ถœํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์ถฉ๋ถ„ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›๊ณ  ํ†ตํ•ฉ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ด ๋ฌธ์ œ๋ฅผ ์ž ๊ทธ๊ฒ ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ์งˆ๋ฌธ ๋ฐ ๋‹ต๋ณ€: https://github.com/facebook/react/issues/14920#issuecomment -471070149

useEffect ๋ฐ ์ข…์†์„ฑ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ ค๋ฉด ์—ฌ๊ธฐ๋ฅผ https://overreacted.io/a-complete-guide-to-useeffect/

๊ณง ๋ฌธ์„œ์— ๋” ๋งŽ์€ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๊ทœ์น™์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ๊ฑฐ๋‚˜ ๊ท€ํ•˜์˜ ์‚ฌ๋ก€๊ฐ€ ํ•ฉ๋ฒ•์ ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ƒˆ ๋ฌธ์ œ๋ฅผ ์ œ์ถœํ•˜์‹ญ์‹œ์˜ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰