React Hooks: useEffect와 useReducer

ian kwon·2023년 10월 21일

React

목록 보기
4/4

React Hooks는 함수형 컴포넌트에서도 state와 lifecycle 기능을 사용할 수 있게 해주는 API입니다. 그중에서 useEffectuseReducer에 대해서 알아보겠습니다.

useEffect란?

useEffect는 컴포넌트가 랜더링된 이후에 어떠한 작업을 수행해야 할 떄 사용하는 Hook입니다.

useEffect(() => {
  // 컴포넌트가 마운트되거나 업데이트될 때 실행될 로직
  console.log('component rendered');

  return () => {
    // 컴포넌트가 언마운트될 때 실행될 로직
    console.log('component will unmount');
  };
}, [dependencyList]);

dependencyList에 의존성 배열을 전달하여 특정 값이 변경될 때만 effect를 실행하도록 조절할 수 있습니다.

useReducer란?

useReducer는 복잡한 컴포넌트 상태 로직을 관리할 수 있는 Hook입니다. useState보다 더 유연한 상태 관리를 할 때 주로 사용합니다.

기본적으로, useReducer는 현재 상태와 액션 객체를 받아 새로운 상태를 반환하는 리듀서 함수를 사용합니다.

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}

그렇다면 여기에서 useStateuseReducer는 둘 다 상태 관리를 위한 Hook인데 뭐가 다른지 궁금해 할 수도 있습니다. 아래의 내용을 보면 차이가 분명이 존재한다는 것을 알 수 있을 것입니다.

useState vs useReducer

1. useState

  • 간단한 상태 로직을 관리할 때 주로 사용됩니다.
  • 상태 값과 그 값을 설정하는 함수 두 개를 반환합니다.
  • 주로 단순한 값(문자열, 숫자, boolean) 또는 객체, 배열 등의 상태를 관리할 때 사용됩니다.
const [count, setCount] = useState(0);

2. useReducer

  • 복잡한 상태 로직이나 다음 상태가 이전 상태에 의존적일 때 유용합니다.

  • 상태 값과 그 상태를 변화시키기 위한 dispatch 함수를 반환합니다.

  • 액션을 기반으로 상태 변화 로직을 분리하여 관리할 수 있습니다.

const [state, dispatch] = useReducer(reducer, initialState);

3. 차이점

  • 복잡도: useState는 간단한 상태 관리에 적합하고, useReducer는 복잡한 상태 로직이나 중첩된 상태를 다룰 때 더 적합합니다.

  • 상태 업데이트 방식: useState는 상태를 직접 설정하는 반면, useReducer는 액션을 통해 상태를 업데이트합니다.

  • 재사용성: useReducer에서 리듀서 함수를 분리하면 로직의 재사용성이 높아집니다.

간단한 상태 로직:

  • 단일 값: 상태 값이 단순한 데이터 타입(예: 문자열, 숫자, 불린) 또는 간단한 객체나 배열로 구성된 경우.

  • 독립적인 상태 업데이트: 상태 업데이트가 다른 상태나 액션의 결과에 의존하지 않는 경우.

  • 직관적: 상태 업데이트 로직을 보았을 때, 해당 로직의 동작을 쉽게 이해할 수 있는 경우

const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);

복잡한 상태 로직:

  • 중첩된 상태: 상태 값이 중첩된 객체나 복잡한 데이터 구조를 가지고 있는 경우.

  • 의존적인 상태 업데이트: 상태 업데이트가 다른 상태의 값이나 이전 상태, 혹은 복잡한 조건 로직에 의존하는 경우.

  • 로직의 재사용: 동일한 상태 업데이트 로직이 여러 곳에서 재사용되어야 하는 경우.

  • 사이드 이펙트와의 관련성: 상태 업데이트가 비동기 작업, 외부 데이터 소스와의 상호작용 등의 사이드 이펙트와 밀접하게 관련된 경우.

const initialState = {
  loading: false,
  data: null,
  error: null
};

function reducer(state, action) {
  switch (action.type) {
    case 'FETCH_START':
      return { ...state, loading: true };
    case 'FETCH_SUCCESS':
      return { loading: false, data: action.payload, error: null };
    case 'FETCH_ERROR':
      return { ...state, loading: false, error: action.error };
    default:
      throw new Error();
  }
}
profile
“당신이 두려워하는 일을 매일 하라.” -엘리너 루스벨트-

0개의 댓글