[React] useState vs useReducer

deeยท2022๋…„ 10์›” 17์ผ
4

react

๋ชฉ๋ก ๋ณด๊ธฐ
2/6
post-thumbnail

๐Ÿค” ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์™œ ํ•ด์•ผ ํ• ๊นŒ?

DOM์„ ์ง์ ‘ ์กฐ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. React๋Š” JSX ๋ฌธ๋ฒ•์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ์ฝ”๋“œ๋กœ ๊ฐ€์ƒ DOM์„ ์ƒ์„ฑํ•˜์—ฌ ์‹ค์ œ DOM์— ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋ฐ˜์˜ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ์ค„์ผ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด ๊ฐ€์ƒ DOM์„ ๋งŒ๋“ค ๋•Œ ์ƒํƒœ ๊ฐ’ ๋ณ€ํ™”์— ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žฌ๊ตฌ์„ฑ๋˜๊ณ  ๋ฆฌ๋ Œ๋”๋ง์ด ์ด๋ฃจ์–ด์ง„๋‹ค.

๊ณ ๋กœ ์ƒํƒœ ๊ด€๋ฆฌ๋Š” ๋งค์šฐ ์ค‘์š”ํ•˜๋ฉฐ hook๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด์„œ ๋‹ค์–‘ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ˆ˜๋งŽ์€ ์ƒํƒœ๊ด€๋ฆฌ ๋ฐฉ๋ฒ• ์ค‘์— ๊ธฐ์ดˆ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” useState์™€ useReducer ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•˜๋ฉด์„œ ์ดํ•ดํ•ด๋ณด์ž.


useState

  • state๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ํ•จ์ˆ˜.
  • ์ƒํƒœ์˜ ๊ธฐ๋ณธ๊ฐ’์„ ์ธ์ˆ˜๋กœ ๋„˜๊ฒจ์คŒ.
  • ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ฐฐ์—ด์ด ๋ฐ˜ํ™˜๋จ.
    => 1๋ฒˆ์งธ ์š”์†Œ : ํ˜„์žฌ ์ƒํƒœ, 2๋ฒˆ์งธ ์š”์†Œ: setter ํ•จ์ˆ˜.
  • setter ํ•จ์ˆ˜๋Š” ์ธ์ˆ˜๋กœ ์ „๋‹ฌ ๋ฐ›์€ ๊ฐ’์„ state ๊ฐ’์œผ๋กœ ์„ค์ •.
    => state๊ฐ€ ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง.

๐Ÿ“ ์•„๋ž˜ ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
  1. React์™€ useState๋ฅผ import.
  2. App ์ปดํฌ๋„ŒํŠธ ์ •์˜.
  3. useState๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฌผํ’ˆ ๊ฐœ์ˆ˜๋ฅผ ๊ด€๋ฆฌ. (์ดˆ๊ธฐ๊ฐ’์€ 0)
  4. ๋ฒ„ํŠผ ํด๋ฆญ์‹œ setter ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ƒํƒœ๊ฐ’ ๋ณ€๊ฒฝ.
  5. ์ƒํƒœ๊ฐ’ ๋ณ€๊ฒฝ์œผ๋กœ ํ™”๋ฉด ๋ฆฌ๋ Œ๋”๋ง๋จ.
import React, { useState } from 'react';

const App = () => {
	const [cart, setCart] = useState(0); // ๋ฐฐ์—ด ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น	
  	const onAddHandler = () => {
    	if(cart > 10) {
        	alert('10๊ฐœ ์ด์ƒ์€ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
          	return;
        }
      
      	setCart(prevCart => prevCart + 1);
    }
    
    return (
      	<div>
      		<div>์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฌผํ’ˆ {cart}๊ฐœ</div>
			<button onClick={onAddHandler}>์ถ”๊ฐ€</button>
      	</div>
    );
};

๐Ÿง state ์—…๋ฐ์ดํŠธ์‹œ prevCart์˜ ์˜๋ฏธ๋Š”?
state as snapshot์„ ์˜๋ฏธํ•œ๋‹ค. React๊ฐ€ state ๊ฐ’์„ ๋ณ€๊ฒฝํ• ๋•Œ ๊ฐ€์žฅ ์ตœ์‹ ์˜ state๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๊ฐœ๋…์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.


useReducer

  • ustState๋ณด๋‹ค ์ข€ ๋” ๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉ.
  • reducer ํ•จ์ˆ˜, ์ดˆ๊ธฐ ์ƒํƒœ๊ฐ’, ์ดˆ๊ธฐ ํ•จ์ˆ˜ ์ธ์ˆ˜๋ฅผ ๋ฐ›์Œ.
  • ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ฐฐ์—ด์ด ๋ฐ˜ํ™˜๋จ.
    => 1๋ฒˆ์งธ ์š”์†Œ : ํ˜„์žฌ ์ƒํƒœ, 2๋ฒˆ์งธ ์š”์†Œ: dispatch ํ•จ์ˆ˜.
reducer๊ด€๋ จ ๊ฐœ๋…๋‚ด์šฉ
reducerํ˜„์žฌ state์™€ action์„ ๋‘ ๊ฐœ์˜ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
dispatch๊ฐ€ ์ „๋‹ฌํ•œ ์•ก์…˜ ๊ฐ์ฒด์— ๋”ฐ๋ผ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ
(state, action) => newState์˜ ํ˜•ํƒœ
์ดˆ๊ธฐ ์ƒํƒœ๊ฐ’์ฒ˜์Œ์— ์„ค์ •ํ•ด์ฃผ๋Š” ๊ฐ’
์ดˆ๊ธฐ ํ•จ์ˆ˜์ดˆ๊ธฐ state๋ฅผ ์ง€์—ฐํ•ด์„œ ์ƒ์„ฑ
dispatch์ปดํฌ๋„ŒํŠธ ๋‚ด์˜ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
reducer์˜ ์•ก์…˜ ๊ฐ์ฒด๋ฅผ ๋„˜๊น€

๐Ÿ“ ์•„๋ž˜ ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
  1. React์™€ useReducer๋ฅผ import.
  2. App ์ปดํฌ๋„ŒํŠธ ์ •์˜.
  3. useReducer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฌผํ’ˆ ๊ฐœ์ˆ˜๋ฅผ ๊ด€๋ฆฌ. (์ดˆ๊ธฐ ์ƒํƒœ ๊ฐ’์€ {cart: 0})
  4. ๋ฒ„ํŠผ ํด๋ฆญ์‹œ dispatch ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํƒ€์ž…์ด ADDCART์ธ action ๊ฐ์ฒด ์ „๋‹ฌ.
  5. reducer ํ•จ์ˆ˜๊ฐ€ action ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ ํƒ€์ž…์ด ๊ฐ™์€ ์ผ€์ด์Šค๋ฅผ ์ฐพ์•„ ์ƒํƒœ ๋ณ€๊ฒฝ ํ›„ ๋ฐ˜ํ™˜.
  6. ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ณ  ๋ฆฌ๋ Œ๋”๋ง.
import React, { useReducer } from 'react';

// ์ดˆ๊ธฐ๊ฐ’ 
const initialState = { cart: 0 };

// reducer ํ•จ์ˆ˜
const reducer = (state, action) => {
	switch(action.type){
      case 'ADDCART':
        if(cart > 10) {
        	throw new Error('10๊ฐœ ์ด์ƒ์€ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
        }
        
        return { cart: state.cart + 1 };
    }
};

// App ์ปดํฌ๋„ŒํŠธ
const App = () => {
	const [state, dispatch] = useReducer(reducer, initialState);
  	const onAddHandler = () => dispatch({ type: 'ADDCART' });
  
	return (
    	<div>
      		<div>์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฌผํ’ˆ {state.cart}๊ฐœ</div>
			<button onClick={onAddHandler}>์ถ”๊ฐ€</button>
      	</div>
    )
}

useState vs useReducer

์œ„์˜ ๋™์ผํ•œ ๋กœ์ง์„ useState์™€ useReducer๋กœ ์ž‘์„ฑํ•ด๋ณด์•˜๋‹ค. ์‚ฌ์‹ค ๊ฐ„๋‹จํ•œ ๋กœ์ง์ด๊ธฐ์— ์–ด๋–ป๊ฒŒ ๋ณด๋ฉด useState๋กœ๋งŒ ์ž‘์„ฑ์„ ํ•ด๋„ ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ด์ ์€ ์ž ์‹œ ๋ฐฐ์ œํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

  • onAddHandler ํ•จ์ˆ˜
  1. useReducer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ useState๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ณด๋‹ค ๊ฐ„๊ฒฐ.
  2. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ž‘์„ฑํ•œ ๋ถ€๋ถ„์ด reducer ํ•จ์ˆ˜์— ์žˆ์Œ.
  3. type์„ ํ†ตํ•ด ์–ด๋–ค ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š”์ง€ ๋‚˜ํƒ€๋‚ด ๊ฐ€๋…์„ฑ ์ธก๋ฉด์—์„œ๋„ ์ข‹์Œ.
// useState๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ
const onAddHandler = () => {
  if(cart > 10) {
    throw new Error('10๊ฐœ ์ด์ƒ์€ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
  }

  setCart(prevCart => prevCart + 1);
}

// useReducer๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ
const onAddHandler = () => dispatch({ type: 'ADDCART' });
  • ์ผ๊ด€์„ฑ ๋ฐ ํ™•์žฅ์„ฑ ์ธก๋ฉด
    ์œ„์™€ ๊ฐ™์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ํ•œ๋‘๊ฐœ๊ฐ€ ์•„๋‹ˆ๊ณ  ์ ์  ๋งŽ์•„์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด useReducer๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์ผ๊ด€์„ฑ์žˆ๋Š” ํŒจํ„ด์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
const onAddHandler = () => dispatch({ type: 'ADDCART' });
const onDeleteHandler = () => dispatch({ type: 'DELETECART' });

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ํ›จ์”ฌ ๋” ๊ธธ์–ด์ง€๊ณ  ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ๊ฐ€ ํด ๊ฒฝ์šฐ useReducer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ„๊ฒฐํ•˜๊ณ  ์–ด๋–ค ๋กœ์ง์„ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ผ๊ด€์„ฑ์žˆ๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
๐Ÿšจ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ ์€ ๊ฐœ๋ฐœ ์ƒํ™ฉ์— ๋งž๊ฒŒ hooks๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค!!!


๐Ÿ‘ ์˜ค๋Š˜์˜ ๊ณต๋ถ€ ์ผ๊ธฐ

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


์ฐธ๊ณ  ์ž๋ฃŒ
https://cpro95.tistory.com/m/642
https://react.vlpt.us/basic/07-useState.html
https://velog.io/@tnsdlf158/React-Hooks-useReducer

profile
์›น ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€