우리가 어떠한 상태를 관리할 때는 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 |