Tech Blog of Pinomaker

우리가 어떠한 상태를 관리할 때는 useState()를 사용해서 해왔지만, useState()는 컴포넌트 내부에서 이루어진다는 것이 있다. 그러기에, A 컴포넌트에서 B 컴포넌트로 상태 전달할 때의 어려움도 존재하였다.

 

이를 해결 하는 방법이 useReducer다. useReducer는 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리 시킬 수 있기에, 컴포넌트 바깥에 작성하거나, 다른 파일에서 작성 하고 불러와서 사용할 수도 있다.

 

useReducer에서 reducer는 현재 상태(state)와 액션 객체(action)를 파라미터로 받아 새로운 상태를 반환하는 함수다.

reducer에서 반환하는 상태는 곧 컴포넌트가 가지게 될 새로운 상태가 된다. 여기서 action은 상태를 업데이트를 하기 위한 정보를 가지고 있으며, 주로 type 값을 지닌 객체로 사용하긴 하지만 반드시 따라야하는 규칙은 없다.

function reducer(state, action) {
  /**
  * 새로운 상태를 만드는 로직
  * 그 후 새로운 상태를 만들어서 반환
  */
  return nextState;
}

 

아래의 코드를 보면, action 객체의 형태는 자유인 것을 볼 수 있다. 주로 type 값을 대문자와 -를 이용해서 작성하는 관습이 있지만, 반드시 따라야하는 것은 아니다.

// 카운터에 1을 증가하는 action
{
  type: 'INCREMENT'
}
// 카운터에 1을 감소하는 action
{
  type: 'DECREMENT'
}
// input 값을 바꾸는 액션
{
  type: 'CHANGE_INPUT',
  key: 'name',
  value: 'pino'
}

 

 

reducer에 대해서 알아봤으니, useReducer의 사용 방법에 대해서 알아보자.

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

 

useReducer는 위의 형태로 사용하게 되는 데,  state는 우리가 컴포넌트에서 사용 할 수 있는 상태이며, dispatch는 액션을 발생 시키는 함수인데, 아래와 같이 사용하게 된다.

dispatch({ type: 'INCREMENT' })

 

useReducer에 넣는 첫번째 인자는 reducer 함수이고, 두번째는 초기 상태다.

 

우리는 숫자를 증가, 감소 시키는 컴포넌트를 예제로 작성해보자.

아래의 예제는 증가 버튼을 누르면 숫자가 1 증가하고, 감소 버튼을 누르면 숫자가 1 감소하는 예제이며, 일단 useState를 활용하여 숫자를 관리한다.

import React, { useState } from 'react'

export default function Counter() {
  const [number, setNumber] = useState(0)

  const onIncrease = () => {
    setNumber(current => current + 1)
  }

  const onDecrease = () => {
    setNumber(current => current - 1)
  }
  
  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>증가</button>
      <button onClick={onDecrease}>감소</button>
    </div>
  )
}

 

아래의 코드는 useState가 아닌 useReducer를 활용하여, 상태를 관리한 예제다.

먼저 reducer 함수를 생성하며, action type이 "INCREMENT"일 경우는 상태를 1 증가, "DECREMENT"일 경우에는 1 감소를 시키고 상태를 반환한게 만들고, useReducer를 이용해서 컴포넌트 내부에 생성한 리듀서를 이용하여 상태를 관리할 수 있게 된다.

import React, { useReducer } from 'react'

const reducer = (state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

export default function Counter() {
  const [number, dispatch] = useReducer(reducer, 0)

  const onIncrease = () => {
    dispatch({ type: 'INCREMENT' })
  }

  const onDecrease = () => {
    dispatch({ type: 'DECREMENT' })
  }

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>증가</button>
      <button onClick={onDecrease}>감소</button>
    </div>
  )
}

 

 

'F.E > React' 카테고리의 다른 글

MSW로 Mocking(1) - Brower  (0) 2023.09.23
[React] Cookie + JWT + axios 이용하여 JWT 인증하기.  (0) 2022.09.08
[React] useCallback 사용하기.  (0) 2022.08.26
[React] useMemo 사용하기.  (0) 2022.08.26
[React] useRef 사용하기.  (0) 2022.08.21
profile

Tech Blog of Pinomaker

@pinomaker

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!