안녕하세요. 박기린 입니다.
이번엔 React Hooks 중 하나인 useReducer()에 대해 알아보겠습니다.
useReducer 란 무엇일까?
간단하게 설명하자면, useState()처럼 state를 수정하는 React Hook 함수입니다. 그래서 일반적으로 useState()를 사용하기에, useReducer()를 자주 사용하진 않습니다만, 특수한 경우에 useReducer()가 도움이 될 수 있습니다.
도움이 되는 경우
- state가 엄청 많은 경우
- state를 조작하는 수단이 너무 많은 경우
- 어떤 state가 다른 state로부터 종속된 부분이 많은 경우
위의 경우 useState()를 사용하면 어려움이 있거나 에러가 발생할 수 있습니다. 이때 대체제로 useReducer()를 사용할 수 있습니다.
useReducer() 사용법
const [ state, dispatch함수 ] = useRedcuer( reducer함수, 초기state, 초기함수 )
useState() - [state, setState ] - 처럼,
useRedcuer()도 항상 두 개의 값이 있는 배열 - [state, dispatch함수] - 을 반환합니다. 그래서 배열 비구조화를 사용합니다.
반환되는 두 가지 값은 state와 dispatch 함수입니다.
- state : 최신 state 스냅샷
- dispatch함수 : 최신 state 스냅샷을 업데이트(값을 수정)할 수 있게 해주는 함수이다. (useState()에서 setState()함수와 비슷한 역할)
userReducer() 함수는 3개의 인수를 받습니다.
- reducer함수 : dispatch함수가 작동하는 방식을 정의한다.
- 초기state : 말 그대로 State의 초기 설정값을 정의한다.
- 초기함수 : 초기state를 설정하기 위해 실행해야 하는 함수이다. 예를 들어, http 리퀘스트를 받은 후에 초기 state를 설정해야 하는 상황일 때 유용하다)
useReducer() 사용 예시
예제 : 이메일 주소(String)와 이메일 유효성(Boolean) states를 하나의 email state로 결합한 후 useRedcuer로 관리하기
import React, { useReducer } from "react";
React에서 useReducer()를 임포트합니다.
const [email, dispatchEmail] = useReducer(emailReducer, {
value: "",
isValid: null,
});
초기 state에는 원하는 초기값을 넣어줍니다. 우리가 원하는 것은 이메일 주소와 유효성 여부를 담는 것이기 때문에, 객체 형태로 state를 설정합니다.
// emailReducer : Reducer 함수
const emailReducer = (state, action) => {
if (action.type === "USER_INPUT") {
// 사용자 value를 입력하면
return { value: action.val, isValid: action.val.includes("@") };
}
if (action.type === "INPUT_BLUR") {
// 사용자가 입력을 끝내면 (인풋 포커스를 잃으면)
return { value: state.value, isValid: state.value.includes("@") }; // 이 경우에는 action의 type이외에 페이로드 payload property를 받지 않기 때문에, state를 이용한 기존의 최신 state 스냅샷을 가져와서 사용한다.
}
return { value: "", isValid: false };
};
Reducer 함수는 리액트 컴포넌트 함수 내부에서 만들어진 어떤 데이터도 필요로 하지 않기 때문에, 컴포넌트 함수 밖에서 선언할 수 있습니다.
Redcuer 함수는 두 개의 인수를 받습니다.
- state : 최신 state 스냅샷
- action : dispatch된 액션
그리고 새로운 state 스냅샷을 return 합니다.
dispatch 함수를 사용해보자
reducer함수까지 만들었으니, 이제 dispatch 함수를 사용할 수 있게 됐습니다.
- dispatch 함수는 action 객체를 reducer 함수로 전달하는 역할을 한다.
- action 객체는 type property와 payload property를 가질 수 있다.
- type property는 관용적으로 "영어_대문자"를 사용해서 액션 이름을 전달한다.
- payload property는 관용적으로 val 이라는 프로퍼티 이름을 지정해서 사용한다.
- type property에 따라 리듀서 함수가 어떤 방식으로 작동할 지를 지정할 수 있다.
이제 컴포넌트 함수 내부에, dispatch 함수를 사용하기 위한 핸들러 함수를 구현합니다.
const emailChangeHandler = (event) => {
dispatchEmail({ type: "USER_INPUT", val: event.target.value });
};
이메일 입력창에서 사용자로부터 어떤 입력을 받을 때마다, 위 핸들러 함수가 실행됩니다.
dispatch 함수에는 아래의 프로퍼티로 구성된 객체를 전달합니다. (이 객체를 action 객체라고 부릅니다.)
- type 프로퍼티 : reducer 함수에 USER_INPUT 액션을 disaptch 한다.
- val 프로퍼티 : reducer 함수에 입력받은 값을 전달한다.
const validateEmailHandler = () => {
dispatchEmail({ type: "INPUT_BLUR" });
};
사용자가 입력을 마치고 이메일 입력창 밖으로 나갈 때, 위 핸들러 함수가 실행됩니다.
dispatch 함수에는 객체를 전달합니다.
- type 프로퍼티 : reducer 함수에 USER_INPUT 액션을 disaptch 한다.
<input
type="email"
id="email"
value={email.value}
onChange={emailChangeHandler}
onBlur={validateEmailHandler}
/>
실제 React의 input 컴포넌트에 핸들러함수를 적용시킨 코드는 위와 같습니다.
위 input 컴포넌트에 연결된 핸들러함수들은 이러한 방식으로 작동합니다.
emailChangeHandler는 사용자가 이메일 입력창에 값을 입력할 때마다 작동한다.
dispatchEmail에 ‘USER_INPUT’타입을 지정해주고, payload(val)로 현재 입력값을 넘겨준다. reducer 함수는 if문으로 USER_INPUT 타입의 액션에 걸맞은 행동을 취한다. 입력받은 payload(val)를 email state에 적용한다.
validateEmailHandler는 사용자가 이메일 입력창에서 포커스를 잃을 때마다 작동한다.
dispatchEmail에 ‘INPUT_BLUR’타입을 지정해주고, payload(val)는 넘기지 않는다. reducer 함수는 If 문으로 INPUT_BLUR 타입의 액션에 걸맞은 행동을 취한다. state의 최신 상태를 불러온 후 유효성 검사만 진행한다.
State 관리 - useState vs useReducer
useState
- 주요 state 관리 툴
- 간단하면서 적은 수의 개별 state 및 데이터들을 다루기에 적합
- state의 업데이트가 쉽다
- 따라서 state가 변경되는 경우가 다양하지 않다면, 특히 객체 형태의 state나 그 비슷한 게 없다면 사용하기 적합.
useReducer
- 더 강력한 state관리 툴을 필요로 할 때 - 객체 형태와 같은 복잡한 state
- 복잡한 state 업데이트 로직을 포함한 리듀서 함수가 필요하면 - action에 따라 다양한 업데이트 방식을 필요로 하는 경우 or http 리퀘스트를 요구하는 것처럼 업데이트 방식이 더 복잡한 경우
- 여러 state들로 구성된 데이터를 다루는 경우 (위에서 예시로 사용한 email object state = 이메일 string + 이메일 유효성 bool)
// useState
const [enteredEmail, setEnteredEmail] = useState("");
const [emailIsValid, setEmailIsValid] = useState();
// useReducer
const [email, dispatchEmail] = useReducer(emailReducer, {
value: "",
isValid: null,
});
useRedcuer는 여러 state를 하나의 객체 state로 몰아서 저장하고, reducer 함수를 이용해서 복잡한 업데이트 방식을 간단하게 만들어줍니다.
'JS > React 강의' 카테고리의 다른 글
[React] 16. 리액트 Hooks의 규칙을 알아보자 (0) | 2023.12.11 |
---|---|
[React] 15. 리액트 Context API란 무엇일까? (0) | 2023.12.04 |
[React] 13. useEffect() 사용법 총정리 (0) | 2023.07.20 |
[React] 12. CSS 모듈 사용하기 (0) | 2023.03.28 |
[React] 11. styled-components 사용하기 (0) | 2023.03.27 |