일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- REACT
- preventdefault
- Spring REST Docs
- Crawling
- axios
- T-OTP
- cheerio
- SWAGGER
- Filter
- Spring Security
- SpringRESTDocs
- openapi3
- Reduxpender
- 리액트
- vuejs
- UsernamePasswordAuthenticationFilter
- gradle
- stopPropogation
- AuthenticatoinProvide
- Spring Batch
- vue
- OpenStack
- Pender
- SpringBoot
- cloud native
- Flyway
- tasklet
- MSA
- MFA
- JavaScript
- Today
- Total
Miracle Morning, LHWN
18. useReducer 를 사용해서 상태(State) 업데이트 로직 분리해보기 본문
# 상태를 업데이트하는 방법에는 useState, useReducer가 있다.
다만, useReducer Hook 함수를 사용하면 컴포넌트의 상태 업데이트 로직을 컴포넌트로부터 분리시킬 수 있다.
(컴포넌트 밖, 다른 파일에서도 사용할 수 있다.)
reducer 란
reducer 는 현재 상태(state)와 액션 객체(action)를 파라미터로 받아와서 새로운 상태를 반환해주는 함수
function reducer(state, action) {
// 새로운 상태를 만들어주는 로직
// const nextState = ...
return nextState;
}
reducer 에서 반환하는 상태는 곧 컴포넌트가 지닐 새로운 상태가 된다. action 에는 업데이트를 위한 정보를 가지고 있다.
주로 'type' 이라는 값을 가지고 있는 객체 형태로 사용하지만 필수적으로 따라야하는 것은 아니다.
// action 의 예시
{
type: 'INCREMENT'
}
{
type: 'DECREMENT'
}
{
type: 'CHANGE_INPUT',
key: 'email',
value: 'test@naver.com'
}
{
type: 'ADD_TODO',
todo: {
id: 1,
text: 'useReducer',
done: false
}
}
(※ 객체의 형태는 자유지만 보통 type 값을 '대문자', '_'로 구성한다.)
useReducer 의 사용
# useReducer 를 사용하는 형태는 아래와 같다.
// useReducer([reducer 함수], [초기 상태])
const [state, dispatch] = useReducer(reducer, initialState);
(1) state : 컴포넌트에서 사용할 수 있는 상태 값
(2) dispatch : 액션을 발생시키는 함수 ex) dispatch({ type: 'INCREMENT' })
useReducer 사용해보기 예제 1
이제 useReducer 를 사용할건데 일단 예전에 useState 로 작성했던 컴포넌트를 보자.
import React, { useState } from 'react';
function Counter() {
const [number, setNumber] = useState(0);
const onIncrease = () => {
setNumber(prevNumber => prevNumber + 1);
};
const onDecrease = () => {
setNumber(prevNumber => prevNumber - 1);
};
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
위 코드를 useReducer 를 사용해서 구현해보자
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
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}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
useReducer 사용해보기 예제 2
// App.js
import React, { useRef, useState, useMemo, useCallback } from 'react';
import UserList from './UserList';
import CreateUser from './CreateUser';
function countActiveUsers(users) {
console.log('활성 사용자 수를 세는중...');
return users.filter(user => user.active).length;
}
const initialState = {
inputs: {
username: '',
email: ''
},
users: [
{
id: 1,
username: 'velopert',
email: 'public.velopert@gmail.com',
active: true
},
{
id: 2,
username: 'tester',
email: 'tester@example.com',
active: false
},
{
id: 3,
username: 'liz',
email: 'liz@example.com',
active: false
}
]
};
function App() {
return (
<>
<CreateUser />
<UserList users={[]} />
<div>활성사용자 수 : 0</div>
</>
);
}
export default App;
일단 (1) reducer(state, action) 함수를 만들고, (2) App() 컴포넌트 내부에서 useReducer 를 사용해준다.
그리고 비구조화 할당 문법을 통해 state 로부터 추출하여 각 컴포넌트에게 전달해준다.
const { user } = state;
const { username, email } = state.inputs;
(3) 이제 reducer(state, action) 함수 로직을 구현해주면 된다.
먼저 CHANGE_INPUT 부터 구현하는데 CHANGE_INPUT 액션 객체를 이용하여 inputs 상태를 업데이트 해준다.
function reducer(state, action) {
switch (action.type) {
case 'CHANGE_INPUT':
return {
...state,
inputs: {
...state.inputs,
[action.name]: action.value
}
};
default:
return state;
}
}
...
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
const { users } = state;
const { username, email } = state.inputs;
const onChange = useCallback(e => {
const { name, value } = e.target;
dispatch({
type: 'CHANGE_INPUT',
name,
value
});
}, []);
...
그렇다면 useReducer vs useState 중에 뭘 써야 할까?
만일 컴포넌트에서 관리하고 있는 값이 1개 뿐이고, 그 값이 단순한 숫자/문자열/boolean 값일 경우 useState 가 편할 것이다.
const [value, setValue] = useState(true);
하지만 컴포넌트에서 관리하고 있는 값이 여러 개이고, 상태의 구조가 복잡하다면 useReducer 가 편할 것이다.
※ 팁! velopert 강사님은 'setter 를 한 함수에서 여러 번 사용해야 하는 일이 발생하는 경우'에 useReducer 사용에 대한 고민을 시작하신다고 한다.
출처 : https://react.vlpt.us/basic/20-useReducer.html
'IT 기술 > [React] 기본' 카테고리의 다른 글
20. React의 Hooks 총정리! (0) | 2021.05.25 |
---|---|
19. Custom Hook 만들어보기 (0) | 2021.05.25 |
17. React.memo 를 이용하여 컴포넌트 리렌더링을 방지하기 (0) | 2021.05.25 |
16. useCallback 이용하여 함수 재사용하기 (0) | 2021.05.25 |
15. useMemo 를 이용해서 연산된 값을 재사용 (0) | 2021.05.25 |