[React/Udemy] 강의 내용 정리 - Section #10 - useReducer()

ZenTechie·2023년 4월 20일
0

Udemy

목록 보기
2/4
post-thumbnail

useReducer 란?

useReducer는 React에 내장된 Hook이며,
useState와 비슷하게 state 관리를 도와주지만, 더 복잡한 state에 특히 유용하게 쓰인다


useReducer 살펴보기

const [state, dispatchFn] = useReducer(reducerFn, initialState, initFn)

state : 최신 state 스냅샷
dispatchFn : state를 update할 수 있는 함수(새로운 state값을 설정하는 대신, 액션을 디스패치 한다.)
reducerFn : 액션을 소비하는 함수. 최신 state 스냅샷을 자동으로 가져온다. 또한, 디스패치된 액션을 가져온다. (새 액션이 디스패치될 때 마다 이 함수가 호출된다.)
initialState : 초기 state
initFn : 초기 state를 설정하는 함수


useReducer의 역할

useReducer는 그래서 언제 쓰이는 것인가?

가끔, 복잡한 state를 가질 경우가 있다.
예를 들어, 다수의 state들이 함께 속해 있는 경우 또는 같이 바뀌거나 서로 연관된 경우,
다른 state를 기반으로 하는 state를 업데이트 할 때 등이 있다.

이 경우에 useState()는 다수의 state들을 관리하기에 부족할 수 있다.
(코드가 bad, inefficient해질 수 있다.🤮)

이때 사용가능한 것이, useReducer()이다.

즉, 더 복잡한 state들의 관리에 유용하게 쓰인다.


굳이 useReducer를 사용해야 하나?

useReducer를 사용하면, state를 처리하는 로직 부분을 컴포넌트에서 분리시켜 작성할 수 있다.

즉, 컴포넌트를 최적화 시킬 수 있다는 의미이다.

다음의 예시 코드를 보자.

useState 사용 시

const Login = (props) => {
  const [enteredEmail, setEnteredEmail] = useState('');
  const [emailIsValid, setEmailIsValid] = useState();
  const [enteredPassword, setEnteredPassword] = useState('');
  const [passwordIsValid, setPasswordIsValid] = useState();

  // email 인풋 필드에 값이 변경 시 호출하는 핸들러 함수
  const emailChangeHandler = (event) => {
    setEnteredEmail(event.target.value);
  };
  // password 인풋 필드에 값이 변경 시 호출하는 핸들러 함수
  const passwordChangeHandler = (event) => {
    setEnteredPassword(event.target.value);
  };
  // email 인풋 필드를 올바르게 입력했는지 검사하는 핸들러 함수
  const validateEmailHandler = () => {
    setEmailIsValid(enteredEmail.includes('@'));
  };
  // password 인풋 필드를 올바르게 입력했는지 검사하는 핸들러 함수
  const validatePasswordHandler = () => {
    setPasswordIsValid(enteredPassword.trim().length > 6);
  };

useReducer 사용 시


// 컴포넌트 외부
const emailReducer = (state, action) => {
  if (action.type === "USER_INPUT") {
    return { value: action.val, isValid: action.val.includes("@") };
  }
  if (action.type === "INPUT_BLUR") {
    return { value: state.value, isValid: state.value.includes("@") }; // 이전에 가졌던 state.value가 value가 된다.
  }
  return { value: "", isValid: false };
};

const passwordReducer = (state, action) => {
  if (action.type === "USER_INPUT") {
    return { value: action.val, isValid: action.val.trim().length > 6 };
  }
  if (action.type === "INPUT_BLUR") {
    return { value: state.value, isValid: state.value.trim().length > 6 };
  }
  return { value: "", isValid: false };
};

// Login 컴포넌트
const Login = (props) => {
  const [emailState, dispatchEmail] = useReducer(emailReducer, {
    value: "",
    isValid: undefined,
  });

  const [passwordState, dispatchPassword] = useReducer(passwordReducer, {
    value: "",
    isValid: undefined,
  });

  const emailChangeHandler = (event) => {
    dispatchEmail({ type: "USER_INPUT", val: event.target.value });
  };

  const passwordChangeHandler = (event) => {
    dispatchPassword({ type: "USER_INPUT", val: event.target.value });
  };

  const validateEmailHandler = () => {
    dispatchEmail({ type: "INPUT_BLUR" });
  };

  const validatePasswordHandler = () => {
    dispatchEmail({ type: "INPUT_BLUR" });
  };

useReducer를 사용했을 때 reducer 함수"Login 컴포넌트 외부로 뺀" 모습을 볼 수 있다.

이것이 가능한 이유는, reducer 함수 내부에서는 컴포넌트 함수 내부에서 만들어진 어떤 데이터도 필요하지 않기 때문이다.

따라서, reducer 함수는 컴포넌트 함수의 범위 밖에서 만들어질 수 있다.
(reducer 함수 내부에서 요청되고 사용되는 모든 데이터는 리액트가 이 함수를 실행할 때 자동으로 전달된다.)

useReducer vs useState

공통적으로 useReduceruseState는 모두 state를 처리하는 Hook이다.
그렇다면, useReduceruseState언제 어느것을 써야하는지 판단 할 수 있을까?

  • useState
    • 주요 state 관리 도구이다.
    • 개별 state 및 데이터들을 다루기에 적합하다.
    • 간단한 state에 적합하다.
    • state의 업데이트가 쉽고, 몇 종류 안되는 경우에 적합하다.
  • useReducer
    • state로서의 객체가 있는 경우
    • 복잡한 state가 있는 경우
    • 관리해야 할 state가 여러개일 경우
    • 다른 연관된 state 조각들로 구성된 어떤 state를 관리해야 하는 경우
profile
데브코스 진행 중.. ~ 2024.03

0개의 댓글