-
20. useReducer 이해하기 - 리액트 입문 | 벨로퍼트Front-end/React.js 2020. 7. 1. 20:53반응형
우리가 이전에 만든 사용자 리스트 기능에서의 주요 상태 업데이트 로직은 App 컴포넌트 내부에서 이루어졌었습니다. 상태를 업데이트 할 때에는 useState 를 사용해서 새로운 상태를 설정해주었는데요, 상태를 관리하게 될 때 useState 를 사용하는것 말고도 다른 방법이 있습니다. 바로, useReducer 를 사용하는건데요. useState 는 설정하고 싶은 다음 상태를 직접 지정해주는 것으로 상태를 업데이트하는 반면, useReducer 는 액션이라는 개체를 기반으로 상태를 업데이트 합니다. 여기서 액션 객체는 업데이트할 때 참조하는 객체입니다.
이 Hook 함수를 사용하면 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있습니다. 상태 업데이트 로직을 컴포넌트 바깥에 작성 할 수도 있고, 심지어 다른 파일에 작성 후 불러와서 사용 할 수도 있지요.
App 컴포넌트에서 useReducer 를 사용해보기전에 우리가 useState 를 처음 배울 때 만들었던 Counter.js 컴포넌트에서 useReducer 를 사용해보겠습니다.
이전에 작성한 코드를 다시 볼까요?
/src/Counter.js :
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 Hook 함수를 사용해보기전에 우선 reducer 가 무엇인지 알아보겠습니다. reducer 는 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수입니다.
*reducer: 상태를 업데이트 하는 함수
function reducer(state, action) { // 새로운 상태를 만드는 로직 // const nextState = ... return nextState; }
reducer 에서 반환하는 상태는 곧 컴포넌트가 지닐 새로운 상태가 됩니다.
여기서 action 은 업데이트를 위한 정보를 가지고 있습니다. 주로 type 값을 지닌 객체 형태로 사용하지만, 꼭 따라야 할 규칙은 따로 없습니다.
액션의 예시들을 확인해볼까요?
// 카운터에 1을 더하는 액션 { type: 'INCREMENT' } // 카운터에 1을 빼는 액션 { type: 'DECREMENT' } // input 값을 바꾸는 액션 { type: 'CHANGE_INPUT', key: 'email', value: 'tester@react.com' } // 새 할 일을 등록하는 액션 { type: 'ADD_TODO', todo: {id: 1, text: 'useReducer 배우기', done: false,} }
보신 것 처럼 action 객체의 형태는 자유입니다. type 값을 대문자와 _ 로 구성하는 관습이 존재하기도 하지만, 꼭 따라야 할 필요는 없습니다.
자, 이제 reducer 를 배웠으니 useReducer 의 사용법을 알아봅시다. useReducer 의 사용법은 다음과 같습니다.
const [state, dispatch] = useReducer(reducer, initialState);
여기서 state 는 우리가 앞으로 컴포넌트에서 사용 할 수 있는 상태를 가르키게 되고, dispatch 는 액션을 발생시키는 함수라고 이해하시면 됩니다. 이 함수는 다음과 같이 사용합니다: dispatch({ type: 'INCREMENT' }).
그리고 useReducer 에 넣는 첫번째 파라미터는 reducer 함수이고, 두번째 파라미터는 초기 상태입니다.
그럼, Counter 컴포넌트를 만약에 useReducer 로 구현한다면 어떻게 바뀌는지 알아볼까요?
다음 코드를 한번 따라서 작성해보세요.
/src/Counter.js :
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; // 준비하지 않은 액션이 들어와도 어떤 일도 일어나지 않는다. // throw new Error ("Unhandled Action"); // 준비하지 않은 액션이 들어오면 콘솔에서 에러가 생성된다. } } function Counter() { const [number, dispatch] = useReducer(reducer, 0); const onIncrease = () => { dispatch({ type: 'INCREMENT' }); }; const onDecrease = () => { dispatch({ type: 'DECREMENT' }); }; return ( ... ); } export default Counter;
잘 작동하는지도 확인해볼까요?
index.js 파일을 열어서 App 대신 Counter 를 렌더링해보세요.
/src/index.js :
... import Counter from './Counter'; ReactDOM.render(<Counter />, document.getElementById('root'));
그리고 카운터가 잘 작동하는지 확인해보세요.
잘 작동하는것을 확인했다면 App 컴포넌트를 렌더링하도록 다시 복구하세요.
반응형'Front-end > React.js' 카테고리의 다른 글
22. 커스텀 Hooks 만들기 - 리액트 입문 | 벨로퍼트 (0) 2020.07.03 21. App 컴포넌트를 useReducer 로 구현하기 - 리액트 입문 | 벨로퍼트 (0) 2020.07.01 19. React.memo 를 사용한 컴포넌트 리렌더링 방지 - 리액트 입문 | 벨로퍼트 (0) 2020.06.30 18. useCallback 을 사용하여 함수 재사용하기 - 리액트 입문 | 벨로퍼트 (0) 2020.06.30 17. useMemo 를 사용하여 연산한 값 재사용하기 - 리액트 입문 | 벨로퍼트 (0) 2020.06.30