본문 바로가기
Frontend/React

React useReducer 개념 및 사용 방법

by Forsaken Developer 2023. 1. 25.
728x90
728x90

React useReducer 개념 및 사용 방법

useReducer 개념

useReducer는 state 관리를 도와주는 hook으로 useState와 약간 비슷하다.

하지만 더 많은 기능이 있고 더 복잡한 state에 특히 유용하다.

예를 들어 여러 state들이 함께 속해 있는 경우, 여러 state가 같이 바뀌거나 서로 관련된 경우useState에서 얻은 state는 종종 사용 및 관리가 어려워지거나 오류가 발생하기 쉽다.

이런 더 강력한 state 관리가 필요한 경우 useReducer를 useState 대신 쓸 수 있다.

하지만 그렇다고 해서 항상 useReducer를 사용해야 한다는 건 아니며 더 강력하다고 해서 항상 더 좋다고 할 수는 없다.

사용하기 조금 더 복잡하기 때문에 조금 더 설정이 필요하고 대부분의 경우에는 useState를 사용하는 것이 좋다.

그러나 useReducer를 사용할만한 가치가 있는 경우가 있다.

useReducer 사용 방법

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

useReducer의 기본적인 사용방법이다.

useState처럼 useReducer도 항상 두 개의 값이 있는 배열을 반환하며 Array destructuring을 사용할 수 있다.

반환되는 두 가지 값은 최신 state 스냅샷과 업데이트할 수 있게 해주는 함수이다.

state 업데이트 함수는 다르게 작동하는데 새로운 state 값을 설정하는 대신 액션을 디스패치한다.

그 액션은 useReducer의 첫 번째 인수인 리듀서 함수(reduceFn)가 소비한다.

리듀서 함수는 최신 state 스냅샷을 자동으로 가져오는 함수이고 디스패치된 액션을 가져온다.

리액트는 새 액션이 디스패치될 때마다 이 리듀서 함수를 호출하고 그러면 이 함수는 리액트가 관리하는 최신의 state 스냅샷을 가져온다.

이 리듀서 함수는 또 한 가지 중요한 일을 하는데 새로 업데이트된 state를 반환하는 것이다.

또한 초기 state나 초기 state가 좀 더 복잡한 경우 초기 state를 설정하기 위해 실행해야 하는 함수를 설정할 수도 있다.

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

대표적인 사용 예시는 사용자 입력 폼이다. 사용자 입력 값과 유효성을 함께 관리 할 수 있다.

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

useState를 사용할 때 값을 업데이트 하기 위해서 상태 변화 함수를 사용했지만 useReducer에서는 액션을 디스패치 해야한다.

dispatchEmail을 호출하여 type과 payload를 액션에 전달한다.

이 액션이 무엇인지는 사용자가 정할 수 있는데 문자열 식별자일 수도 있고 숫자일 수도 있지만 보통은 어떤 식별자를 가지고 있는 객체이다.

이 액션에 payload를 추가할 수도 있고 payload가 없어도 된다.

여기서는 사용자가 입력한 내용을 저장하기 위해서 payload를 추가한다.

const emailReducer = (state, action) => {
  if (action.type === "USER_INPUT") {
    return { value: action.value, isValid: action.value.includes("@") };
  }
  return { value: "", isValid: false };
};

리듀서 함수는 컴포넌트 함수 바깥에 만들 수 있는데 이 리듀서 함수 내부에서는

컴포넌트 함수 내부에서 만들어진 어떤 데이터도 필요하지 않기 때문이다.

리듀서 함수 내부에서 요청되고 사용되는 모든 데이터는 리액트가 이 함수를 실행할 때 자동으로 전달되기 때문에 컴포넌트 함수 밖에서 정의할 수 있다.

이 리듀서 함수는 두 개의 인수, 최신 state 스냅샷과 디스패치된 액션이다.

action의 type을 확인하고 type이 USER_INPUT이라면 액션의 value와 value의 유효성 확인 결과를 최신 state로 반영한다.

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

	const { isValid: emailIsValid } = emailState;
	useEffect(() => {
    const identifier = setTimeout(() => {
      setFormIsValid(emailIsValid);
    }, 1000);

    return () => {
      clearTimeout(identifier);
    };
  }, [emailIsValid]);

}

useEffect와 함께 사용할 경우 의존성을 emailState로 설정한다면 emailState가 변경될 때마다 유효성 검사를 실행한다.

input이 이미 유효한데, 비밀번호에 문자를 추가한 경우라면 문자를 추가하기 전에도 유효했고 이후에도 여전히 유효하기때문에 유효성 검사를 할 필요가 없다.

이럴 때 객체 디스트럭처링을 사용하여 passwordState에서 isValid를 추출할 수 있고 해당 값을 추출하기 위해 별칭을 할당한다.

이제 passwordIsValid 의존성으로 사용할 수 있고 값만 변경되고 유효성은 변경되지 않으면 이 이펙트는 다시 실행되지 않는다.

useReducer와 함께 사용할 때 뿐만 아니라 useEffect를 더욱 최적화 할 수 있는 방법으로 이펙트가 불필요하게 실행되는 것을 피할 수 있다.

useState vs useReducer

언제 useState 또는 useReducer를 사용해야 할지는 반드시 정해진 것이 아니고 사용자의 선택이다.

보통의 경우에는 useState로 시작한다. state에 객체와 같은 것이 없고 간단한 state라면 개별 state 및 데이터들을 다루기에 적합하며 state 업데이트가 쉽다.

그러나 객체 state 또는 복잡한 state가 있다면 useReducer를 고려할 수 있다.

일반적으로 useReducer는 리듀서 함수를 쓸 수 있기 때문에 더 강력하다.

특히 useReducer를 고려해야 하는 경우는 연관된 state들로 구성된 state 관련 데이터를 다루는 form input state 같은 경우이다.

반면에, 절대적으로 항상 useReducer를 사용해야 하는 건 아니다.

예를 들어 두 개의 서로 다른 값을 전환하기만 하는 단순한 state가 있는 경우라면 useReducer는 과할 수 있다.

728x90
반응형

'Frontend > React' 카테고리의 다른 글

리액트가 작동하는 방식  (0) 2023.01.29
React forwardRefs와 useImperativeHandle  (0) 2023.01.28
React Side Effects와 useEffect  (0) 2023.01.24
React useRef 개념 및 사용법  (2) 2023.01.22
React Portals 개념과 사용법  (0) 2023.01.21

댓글