반응형
useReducer
useReducer 란?
useReducer
는 useState
보다 더 다양한 컴포넌트 상태를 관리하는 Hook 입니다. useState
는 컴포넌트 상태를 관리하는 가장 기본적인 Hook 이지만, useReducer
는 복잡한 상태 로직을 다루기에 더 적합합니다.
컴포넌트에서 상태 변화 코드를 쉽게 분리할 수 있고, 상태 로직을 컴포넌트 바깥으로 빼내어 재사용할 수 있습니다.
useReducer 사용법
useReducer
는 다음과 같이 사용합니다.
const [state, dispatch] = useReducer(reducer, initialState)
state
: 현재 상태dispatch
: 액션을 발생시키는 함수, 액션을 발생시키면 리듀서 함수가 호출되어 상태가 변경됩니다.reducer
: 상태를 변경하는 함수initialState
: 초기 상태
useReducer 예제
- useStaet 사용
useState 를 사용하여 컴포넌트 상태를 관리하는 예제로 상태관리가 복잡해질수록 코드가 복잡해 관리가 어려워집니다.
또한 상태를 변경하는 로직이 컴포넌트 안에 선언되어 있어 재사용이 어렵습니다.
import React, { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
const onIncrease = () => {
setCount(count + 1)
}
const onDecrease = () => {
setCount(count - 1)
}
return (
<div>
<h1>{count}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
)
}
export default Counter
- useReducer 사용
useReducer 를 사용하여 컴포넌트 상태를 관리하는 예제로 상태관리가 복잡해져도 코드가 간결해집니다.
또한 상태를 변경하는 로직이 컴포넌트 바깥에 선언되어 있어 재사용이 용이합니다.
import React, { useReducer } from 'react'
// reducer 함수로 상태를 변경
// state : 현재 상태
// action : 상태를 변경할 때 참조하는 값
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { counter: state.counter + 1 }
case 'decrement':
return { counter: state.counter - 1 }
case 'reset':
return { counter: 0 }
default:
return state
}
}
function Counter() {
// useReducer 로 상태 관리
// state : 현재 상태
// dispatch : 액션을 발생시키는 함수
// reducer : 상태를 변경하는 함수
// initialState : 초기 상태
const [state, dispatch] = useReducer(reducer, {
counter: 0,
})
return (
<div>
<h1>Counter</h1>
<p>Current count: {state.counter}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+1</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-1</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
)
}
export default Counter
useReducer 여러 상태 사용
useReducer 를 사용하여 여러 상태를 관리할 수 있습니다.
import React, { useReducer } from 'react'
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, counter: state.counter + 1 }
case 'decrement':
return { ...state, counter: state.counter - 1 }
case 'reset':
return { ...state, counter: 0 }
default:
return state
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, {
counter: 0,
name: 'counter',
})
return (
<div>
<h1>
{state.name}: {state.counter}
</h1>
<button onClick={() => dispatch({ type: 'increment' })}>+1</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-1</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
)
}
export default Counter
할 일 관리 앱 상태 관리
앞에서 만든 할 일 관리 앱 상태 관리 예제를 useReducer 로 변경해보겠습니다.
// src/components/App.js
import React, { useReducer } from 'react'
import TodoHd from './TodoHd'
import TodoEditor from './TodoEditor'
import TodoList from './TodoList'
const mockTodo = [
{
id: 1,
isDone: false,
task: '고양이 밥주기',
createdDate: new Date().getTime(),
},
{
id: 2,
isDone: false,
task: '감자 캐기',
createdDate: new Date().getTime(),
},
{
id: 3,
isDone: false,
task: '고양이 놀아주기',
createdDate: new Date().getTime(),
},
]
// reducer 함수로 상태를 변경합니다.
// state : 현재 상태
// action : 상태를 변경할 때 참조하는 값
function reducer(state, action) {
switch (action.type) {
case 'ADD':
return [action.payload, ...state]
case 'UPDATE':
return state.map((it) => (it.id === action.payload ? { ...it, isDone: !it.isDone } : it))
case 'DELETE':
return state.filter((it) => it.id !== action.payload)
default:
return state
}
}
function App() {
// useReducer를 이용하여 상태를 관리합니다.
// 첫 번째 인수로 reducer 함수를, 두 번째 인수로 초기 상태를 전달합니다.
// 반환값으로 state와 dispatch 함수를 받습니다.
// state : 현재 상태
// dispatch : action을 발생시키는 함수
// dispatch 함수를 이용하여 action을 발생시키면 reducer 함수가 호출됩니다.
// reducer 함수가 호출되면 state가 변경됩니다.
// state가 변경되면 컴포넌트가 리렌더링됩니다.
const [todo, dispatch] = useReducer(reducer, mockTodo)
const addTodo = (task) => {
const newTodo = {
id: Date.now(),
isDone: false,
task,
createdDate: new Date().getTime(),
}
dispatch({ type: 'ADD', payload: newTodo })
}
const onUpdate = (id) => {
dispatch({ type: 'UPDATE', payload: id })
}
const onDelete = (id) => {
dispatch({ type: 'DELETE', payload: id })
}
return (
<div>
<TodoHd />
<TodoEditor addTodo={addTodo} />
<TodoList todo={todo} onUpdate={onUpdate} onDelete={onDelete} />
</div>
)
}
export default App
반응형
'Front > React' 카테고리의 다른 글
Context API로 전역 상태 관리하기 (0) | 2024.03.20 |
---|---|
타입스크립트 개요 및 개발 환경 구성 (0) | 2024.03.19 |
최적화 - React 배우기 (0) | 2024.03.18 |
React를 이용한 할 일 관리 앱 만들기 (0) | 2024.03.14 |
useEffect, 생명주기 - React 배우기 (0) | 2024.03.11 |