๐Ÿ‘ฉ‍๐Ÿ’ป/React

[React.js Hooks] useState, useEffect, useReducer

ํ•œ๋‚˜ 2021. 2. 28. 22:48


useState

๊ธฐ๋ณธ Hook์— ์†ํ•˜๋Š” useState. ์ƒํƒœ ์œ ์ง€ ๊ฐ’๊ณผ ๊ทธ ๊ฐ’์„ ๊ฐฑ์‹ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น์„ ํ†ตํ•ด ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ฒ˜์Œ ๋ Œ๋”๋ง์ด ๋œ ์‹œ์ ์— ๋ฐ˜ํ™˜๋œ state ๊ฐ’์€ useState์ด ๋‘ ๋ฒˆ์งธ ์ธ์ž ๊ฐ’๊ณผ ๊ฐ™๋‹ค.

์ฝ”๋“œ ์ƒ๋‹จ์— useState๋ฅผ importํ•ด์ค€ ๋’ค, ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— const \[value, setValue\] = useState(0); ๋กœ value์˜ ์ดˆ๊ธฐ ์ƒํƒœ๊ฐ’์„ useState์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ†ตํ•ด 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•ด์ค€๋‹ค. ์ดํ›„, +1, -1์ด๋ผ๋Š” ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ๋Š” setValue ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ธฐ์กด value์— 1์„ ๋”ํ•œ ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ, ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์ค€๋‹ค. setValue ํ•จ์ˆ˜๋Š” ์ƒˆ๋กœ์šด state ๊ฐ’์„ ์ธ์ž๋กœ ๋ฐ›์•„ ์ปดํฌ๋„ŒํŠธ Re-rendering์„ ์‹œํ‚จ๋‹ค. ์ดํ›„ ๋ Œ๋”๋ง๋œ state ๊ฐ’์€ ์—…๋ฐ์ดํŠธ๋œ state ๊ฐ’์ด๋‹ค.

useState๋Š” ํ•„์š”ํ•œ ๋งŒํผ ์„ ์–ธํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , useState ๋ฌธ๋ฒ•์ด ๋‚ฏ์„ค๋‹ค๋ฉด ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น(Destructuring Assignment)์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. -> Reference์˜ ๋งํฌ ํ™•์ธ

useEffect

 

useEffect๋Š” ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค (๋‹ค์–‘ํ•œ ์กฐ๊ฑด ํ•˜์—) ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•ด์ฃผ๋Š” Hook์ด๋‹ค. ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ componentDidMount๋‚˜ componentDidUpdate๋ฅผ ํ•ฉ์นœ ์ƒํƒœ์ด๋‹ค. (๋”ฐ๋ผ์„œ ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์œผ๋กœ useEffect๋ฅผ ๋‹ค๋ฅด๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.)

 

์œ„ ์ฝ”๋“œ์—์„œ๋Š” ๋ Œ๋”๋ง ์ดํ›„ 'Rendered'๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ์ถœ๋ ฅ๋˜๋„๋ก ํ–ˆ๋‹ค. ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ์ด ๋ฌธ๊ตฌ๊ฐ€ ์ถœ๋ ฅ๋  ๊ฒƒ์ด๋‹ค. ๋งŒ์ผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋ Œ๋”๋ง๋œ ์‹œ์ ์—๋งŒ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜๋ฅผ ์“ฐ๊ณ ์ž ํ•œ๋‹ค๋ฉด (์—…๋ฐ์ดํŠธ๋  ๋•Œ ํ•ด๋‹น ์ž‘์—…์€ ๋ฌด์‹œ๋œ๋‹ค.) useEffect์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋นˆ ๋ฐฐ์—ด์„ ๋„ฃ์–ด์ค€๋‹ค.

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

์ฒ˜์Œ ๋ Œ๋”๋ง์ด ๋  ๋•Œ๋งŒ ๋ฌธ๊ตฌ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

์ฒ˜์Œ ๋ Œ๋”๋ง๋œ ์ดํ›„(์ฆ‰ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ๋งˆ์šดํŠธ๋œ ์ดํ›„)์— ํŠน์ • ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งŒ ์‹คํ–‰๋˜๋„๋ก ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋นˆ ๋ฐฐ์—ด์„ ์‚ฝ์ž…ํ•˜๋Š” ๋Œ€์‹  Watchํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐ’์„ ๋นˆ ๋ฐฐ์—ด์— ๋„ฃ์–ด์ค€๋‹ค.

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

์ด๋ฆ„: ํ•œ๋‚˜, ๋‹‰๋„ค์ž„: ํ•œ๋‚˜๋‹‰๋„ค์ž„์ด๋ผ๊ณ  ํƒ€์ดํ•‘์„ ํ•œ ์ดํ›„ ํ™”๋ฉด
์ฝ˜์†”์—๋Š” 'ํ•œ๋‚˜๋‹‰๋„ค์ž„'์ด๋ผ๋Š” ๋‚ด์šฉ์€ Watch ๋˜์ง€ ์•Š๋Š”๋‹ค.

useEffect๋กœ๋Š” cleanup ํ•จ์ˆ˜๋ฅผ ์“ธ ์ˆ˜๋„ ์žˆ๋‹ค. cleanup ํ•จ์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ unmount ๋˜๊ธฐ ์ง์ „, ํ˜น์€ ์—…๋ฐ์ดํŠธ๋˜๊ธฐ ์ง์ „์— ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์„ ๋งํ•˜๊ณ , return์„ ํ†ตํ•ด ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

์œ„ ์ฝ”๋“œ์—๋Š” 'cleanup'์ด๋ผ๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๋Š” cleanup ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ณ  ์žˆ๋‹ค. update๋  ๋•Œ๋งˆ๋‹ค cleanup์„ ํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด(=unmount ์‹œ์—๋งŒ ๋™์ž‘ํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด) ์•„๊นŒ์ฒ˜๋Ÿผ useEffect hook์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋นˆ ๋ฐฐ์—ด์„ ์‚ฝ์ž…ํ•œ๋‹ค.

useReducer

Redux๋ฅผ ๊ณต๋ถ€ํ•  ๋•Œ๋„ ๋“ฑ์žฅํ•˜๋Š” Reducer. Redux๊ฐ€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ ๋งŒํผ useReducer Hook๋„ ์—ฌ๋Ÿฌ ์ƒํƒœ๋ฅผ ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์—์„œ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ณ ์ž ํ•  ๋•Œ ์“ฐ์ธ๋‹ค๋Š” ๊ฐœ๋…์ด๋‹ค. useReducer๋Š” ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋งํ•˜๋Š” state, ์—…๋ฐ์ดํŠธ๋ฅผ ๋™์ž‘์‹œํ‚ค๊ธฐ ์œ„ํ•œ action, ๊ทธ๋ฆฌ๊ณ  ์ด ์•ก์…˜์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” dispatch๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๋ฐ”๋€Œ๋Š” ์—ฌ๋Ÿฌ ์ƒํƒœ๋ฅผ ์ถ”์  ๋ฐ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด action์ด๋ผ๋Š” ๊ฐœ๋…์ด ์กด์žฌํ•œ๋‹ค. Vue๋ฅผ ๊ณต๋ถ€ํ•  ๋•Œ Vuex์—์„œ mutation, commit ๋“ฑ์˜ ๊ฐœ๋…์ด ๋“ฑ์žฅํ–ˆ๋˜ ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค.

 

๊ฐ€์žฅ ์ฒ˜์Œ useState๋ฅผ ์ด์šฉํ•ด Counter๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฒƒ์„ useReducer๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

CounterReducer ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ์•„๋ž˜์˜ useReducer ํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ์ž‘์„ฑํ•œ reducer ํ•จ์ˆ˜, ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ์ดˆ๊ธฐ๊ฐ’ ์„ ์–ธ์ด ๋“ค์–ด๊ฐ„๋‹ค. ์ด๋ฅผ ํ†ตํ•ด state, dispatch๋ฅผ ๋ฐ›์•„์™€ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค. dispatch๋Š” ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์•ก์…˜์„ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. dispatch(action)์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋˜๋ฉฐ, ์‹คํ–‰ ์‹œ Reducer ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

 

useReducer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ์—…๋ฐ์ดํŠธ ๋กœ์ง์„ ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€๋กœ ๋นผ๋‚ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. ๋˜ ๋‹จ์ผํ•œ ๋ฌธ์ž๋‚˜ ์ˆซ์ž ๊ฐ™์€ ๋‹จ์ˆœ ๋ฐ์ดํ„ฐ ์ด์™ธ์˜ ๋ณด๋‹ค ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค. ์ด๋ฅผ ์œ„ํ•ด useEffect ์˜ˆ์ œ๋ฅผ ์œ„ํ•ด ์ž‘์„ฑํ•œ Info.js ์ปดํฌ๋„ŒํŠธ๋กœ ๋Œ์•„๊ฐ€๋ณด์ž.

 

InfoReducer ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์— state, action์„ ๊ฐ–๋Š” reducer ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค. rest ... syntax๋ฅผ ์จ์„œ ๊ธฐ์กด์˜ state๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๊ณ  ์žˆ๋‹ค. action์˜ name์€ key์—, value๋Š” value์— ํ• ๋‹นํ•œ๋‹ค.

 

InfoReducer ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ useReducer๋Š” reducer๋ฅผ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ฐ€์ง€๋ฉฐ, ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๊ฐ์ฒด ๋‚ด name, nickname์˜ ์ดˆ๊ธฐ๊ฐ’์„ ๊ฐ๊ฐ ๋นˆ ๋ฌธ์ž์—ด๋กœ ์„ ์–ธํ•ด์ค€๋‹ค.

 

๊ธฐ์กด Info ์ปดํฌ๋„ŒํŠธ๋Š” input์˜ ๊ฐœ์ˆ˜์— ๋”ฐ๋ผ onChange ์ด๋ฒคํŠธ๋ฅผ ๊ฐ๊ฐ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์ง€๋งŒ, useReducer๋ฅผ ์‚ฌ์šฉํ•ด ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ค ์งง๊ฒŒ ์ค„์—ฌ ๊น”๋”ํ•˜๊ฒŒ ์ ์„ ์ˆ˜๋„ ์žˆ๋‹ค. dispatch(action) ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๊ณ , action์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š”๋ฐ, ์—ฌ๊ธฐ์— e.target, ์ฆ‰ input ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” target ์ž์ฒด๋ฅผ action์œผ๋กœ ์‚ผ๊ณ  ์žˆ๋‹ค.

 

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

 

  • ๊ด€์Šต์ ์œผ๋กœ action์€ ์ฃผ๋กœ type ๊ฐ’์„ ๊ฐ€์ง„ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜๊ณ , type์€ ๋Œ€๋ฌธ์ž๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์œ„์˜ CounterReducer.js ์†Œ์Šค์—์„œ๋„ INCREMENT ์ฒ˜๋Ÿผ ๋Œ€๋ฌธ์ž๋กœ ์ž‘์„ฑ๋˜์—ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ’์ด ํ•˜๋‚˜๋ผ๋ฉด, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ฐ’์ด ๋‹จ์ผํ•œ ๋ฌธ์ž์—ด์ด๋‚˜ ์ˆซ์ž๋ผ๋ฉด useState๊ฐ€ ๋‚ซ๋‹ค.
  • ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ•˜์œ„๊ฐ’์„ ๊ฐ–๋Š” ๋ณต์žกํ•œ ๊ตฌ์กฐ์˜ ๋ฐ์ดํ„ฐ๋ผ๋ฉด useReducer๊ฐ€ ์ƒํƒœ ๊ด€๋ฆฌ์— ๋” ๋‚ซ๋‹ค.

Reference

velog.io/@velopert/react-hooks
๋น„๊ตฌ์กฐํ™” ํ• ๋‹น_๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ_ํŠœํ† ๋ฆฌ์–ผ
Hooks API Reference