..

Search

24) State Hooks

State Hooks


State Hooks

React 컴포넌트는 state를 활용하여 가변적인 상태(state)를 기억할 수 있습니다. 예를 들어, Form 컴포넌트는 사용자 입력을 저장하기 위해 state를 사용할 수 있으며, Counter 컴포넌트는 현재 카운터를 저장하기 위해 state를 사용할 수 있습니다.

 

React에서 함수 컴포넌트에 state를 추가하려면 다음 Hook 중 하나를 사용하면 됩니다.

1. useState는 사용자가 직접 업데이트할 수 있는 state 변수를 선언합니다.

2. useReducer는 reducer 함수 내부의 업데이트 로직을 사용하여 state 변수를 선언합니다.


useState Hook

useState는 가장 기본적인 Hook으로 사용자가 직접 업데이트할 수 있는 state 변수를 선언하고 관리할 수 있습니다.

useState 문법
const [state, setState] = useState(initialState)

 

useState는 처음 렌더링을 수행할 때 초기 상태 값(initialState)을 인수로 전달 받고, 최신 state의 값을 유지하는 변수와 그 값을 업데이트할 수 있는 함수를 반환합니다.

예제(Counter.js)
import { useState } from "react";

const Counter = () => {
  // 0을 초기값으로 하는 state와 setState() 함수 생성
  const [state, setState] = useState(0);

  return (
    <div>
      <h1>State 값 : {state}</h1>
      {/* setState() 함수를 사용하여 state의 값을 1씩 증가시킴 */}
      <button onClick={() => setState(state + 1)}>1씩 증가</button>
    </div>
  );
};

export default Counter;

 

우리는 앞서 state에 대해 알아보면서 useState Hook에 대한 내용을 이미 살펴보았습니다.

 

React state 수업 복습하기 ⇒


useReducer Hook

useReducer는 useState보다 좀 더 복잡한 상황에서 state를 사용할 수 있도록 컴포넌트와 state의 업데이트 로직을 서로 분리시켜 관리할 수 있습니다.

useReducer 문법
const [state, dispatch] = useReducer(reducer, initialArg, init?)

 

useReducer의 첫 번째 인수는 reducer 함수를 전달 받으며, 두 번째 인수는 해당 reducer의 기본값을 전달 받습니다. 그리고 현재 state 값과 action을 발생시키는 dispatch 함수를 반환합니다.

useReducer가 반환하는 dispatch 함수를 사용하면 state를 다른 값으로 업데이트하고 리렌더링하도록 설정할 수 있습니다. 이때 dispatch 함수에는 인수로 action 값을 전달해야 합니다.

 

다음 예제는 버튼을 클릭하면 화면의 숫자가 증가하는 카운터 예제를 useState가 아닌 useReducer로 구현한 예제입니다.

예제(Counter.js)
import { useReducer } from "react";

// 컴포넌트와 분리된 state 업데이트 로직
const reducer = (state, action) => {
  if (action.type === "increment") {
    return {
      count: state.count + 1
    };
  }
};

const Counter = () => {
  // reducer 함수와 count의 기본값을 0으로 전달하여 state를 생성함
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <h1>State 값 : {state.count}</h1>
      {/* dispatch 함수에 action.type값으로 'increment'를 전달하여 리렌더링시킴 */}
      <button onClick={() => dispatch({ type: "increment" })}>1씩 증가</button>
    </div>
  );
};

export default Counter;

 

useReducer를 사용했을 때 가장 큰 장점은 컴포넌트에서 state 업데이트 로직을 컴포넌트 외부로 분리시킬 수 있다는 점입니다.

 

reducer에 대한 개념은 이후 Redux를 살펴보면서 좀 더 자세히 알아볼 것입니다. 따라서 reducer 부분이 너무 어렵게 느껴진다면 우선은 건너뛰고 Redux 수업을 공부한 후에 다시 살펴보는 것을 권합니다.

 

React Redux 수업 예습하기 ⇒

 

Redux에서는 Action 객체가 type 필드를 반드시 가지고 있어야 하지만, useReducer에서 사용하는 Action 객체는 type 필드를 가지고 있지 않아도 괜찮습니다.

연습문제