[React hooks] useReducer, useState 비교하기

·2023년 2월 26일
0

react

목록 보기
3/3

useState, useReducer 둘다 state 관리에 유용한 hooks이다.
상태 저장 값과 업데이트하는 함수를 반환한다는 점에서 두가지 기능은 동일하지만 상황에 따라 어떻게 구별해서 사용해야하는지 의문이 들었다. 두 가지 함수를 살펴보며 예시를 만들어보고 비교하여 상황에 맞게 사용할 수 있도록 학습하려 합니다😊

UseState

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

state는 현재 상태를 저장하고 setState는 현재 상태를 업데이트할때 사용하는 함수 입니다. setState에 새 상태 값을 넣어주면 렌더링 대기열에 들어가고 리렌더링 되었을 때 가장 최근에 업데이트된 값을 제공합니다. initialState은 초기 렌더링시 반환되는 값입니다.

👀코드 예시

import { useState } from 'react';

# 
const Home = () => {

    const [data, setData] = useState(1);
    console.log(data);

    const increase = () => {
        setData(data + 10);
        console.log(data);
    }

    const decrease = () => {
        setData(data - 10);
        console.log(data);
    }

    return(        
        <div className="Home">
            <div>
                <p>숫자 : {data}</p>
                <button onClick={increase}>+10</button>
                <button onClick={decrease}>-10</button>
            </div>            
        </div>
    );
};

버튼을 누르면 setData 함수를 호출하여 data 값을 업데이트 합니다. 새로운 data는 home 컴포넌트에 보내지고 컴포넌트가 리렌더링됩니다.

UseReducer

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

useState를 대체하는 함수로 상태를 업데이트 하는 로직을 컴포넌트 바깥으로 분리해서 사용합니다. 컴포넌트를 가볍게 작성할 수 있습니다.

state : 컴포넌트에서 사용되는 현재 상태
dispatch : 상태를 변화시키는 reducer 함수를 실행한다.
reducer : dispatch에서 발생시킨 상태변화를 컴포넌트 밖에서 처리해서 state를 업데이트 시켜준다.
initialState : 초기 상태

🎈dispatch 함수

dispatch({ type : "Decrease"})

dispatch 함수를 호출하면 액션객체를 reducer에 전달한다.
{ type : "Decrease"} : action(=액션 객체)

🎈reducer 함수

function reducer(state, action){
	switch (action.value){
    	case "Increase": {
        	return {count : state.count + 1};
        }
        case "Decrease": {
        	return {count : state.count - 1};
        }
        default: {
       		throw new Error();
        }
    }
}

stateaction 객체를 인자로 받으며 전달받은 상태변화를 컴포넌트 외부에서 처리하여 state를 업데이트 시켜준다.

🎈initialState

const initialState = {count:0};

초기 state 값을 담습니다.

👀코드 예시

const initialState = {count:0};

function reducer (state, action) {
    switch (action.type) {
        case "Increase": {
            return {count : state.count + 1};
        }
        case "Decrease": {
            return {count : state.count - 1};
        }
        case "Multiply": {
            return {count : state.count * state.count};
        }
        case "INIT" : {
            return initialState;
        }
        default : {
            throw new Error("Unsupported action type:", action.type);
        }
    }
}

const DictionaryHome = () => {

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

    return(       
        <div className="DictionaryHome">
            <div className="ex">
                <div>값 : {state.count}</div>
                <button onClick={() => dispatch({ type : "Increase"})}>+</button>
                <button onClick={() => dispatch({ type : "Decrease"})}>-</button>
                <button onClick={() => dispatch({ type : "Multiply"})}>*</button>
                <button onClick={() => dispatch({ type : "INIT"})}>INIT</button>
            </div>          
        </div>
    );
};

💡매커니즘 :: Increase 버튼 눌렀음을 가정한다

초기값 0에 대해 버튼을 클릭하면 dispatch 함수가 type으로 담아 놓은 객체(=액션객체)를 reducer 함수에 전달합니다. reducer에는 (현재 상태, 액션객체) == (0, "Increase")를 받게 됩니다. Switch문을 통해 액션객체와 일치하는 로직을 타고 새로운 state를 반환하게 됩니다.




마무리

useState, useReducer 두 가지 상태관리 함수의 차이를 비교해 보면
useState는 독립적으로 상태관리를 할 때 적합합니다.
useReducer는 복잡한 상태 관리가 필요할 때 적합하며 로직을 컴포넌트 바깥으로 분리해서 컴포넌트가 가벼워지고 상태 관리가 용이합니다.


profile
🙄

0개의 댓글