[React] 4-3장 | useState의 역할과 사용법

Re_Go·2024년 1월 15일
0

React

목록 보기
5/10
post-thumbnail

1. useState란?

useState는 리액트에서 특정 값의 상태를 접근하고 제어할 수 있게 해주는 Hook입니다. 일반적으로 값을 가감하거나 초기화 하기 위한 비동기적 업데이트를 위해 사용되며 가장 보편적으로 사용되는 Hook인데요.

해당 Hook을 사용하기 위해서는 React의 모듈로부터 임포트를 받은 후 해당 Hook을 호출하여 해당 값의 초기 상태를 설정하고, 관리 할 값(변수)과 함수명(해당 값을 관리할)에 각각 구조 분해 할당합니다.

import {useState} from react

const [state, setState] = useState(0) // 해당 값의 초기 상태는 0이고 state는 현재의 상태 값을 나타내는 변수를, setState는 그 값에 상태를 업데이트 하는 메서드 이름입니다.

2. 꼭 useState를 써야해?

만약 리액트에서 제공하는 useState가 아니라 그냥 함수로 직접 상태를 변경한다면 어떻게 될까요?

let anotherCounter = 0

function anotherButton() {
    anotherCounter += 1;
  }

<button className="button" onClick={anotherButton}>{anotherCounter}</button>

위의 예제는 전역 변수 anotherCounter를 핸들링하는 anotherButton 함수를 이용해 해당 변수의 상태를 업데이트 하는 예제인데요.

하지만 아쉽게도 훅스에서 관리하는 변수는 해당 코드문을 이용해 사용자가 리액트에서 를 업데이트 하는 방법으로 허용되지 않습니다. 그 이유는 리액트에서는 상태의 불변성을 유지하면서 변화에 따라 Virtual DOM을 이용해 추적하고, 새로운 상태를 생성된 뒤에 해당 상태를 반영하는 방식을 차용하고 있기 때문인거죠. 한마디로 리액트 라이브러리인 훅스에서 관리하는 변수는 해당 변수를 제어하는 메서드로만 제어가 가능하다는 뜻입니다.

물론 forceUpdate 메서드를 이용해 상태를 강제적으로 변경하는 방법도 존재하나, 가급적이면 리액트에서는 이 Hook을 이용해 상태를 제어하는 방법이 기본이라고 할 수 있는 것이죠.

만약 useState를 자바스크립트로 구현해 보면 다음과 같이 구현해 볼 수 있을 것입니다.

function useState(initialValue) {
  let state = initialValue;

  function setState(Func) {
    state = Func(state);
  }

  return [state, setState];
}

const [state, setState] = useState(0);

function addState() {
  setState(state => state + 1);
}

function subState() {
  setState(state => state - 1);
}

3. useState의 사용법은?

이처럼 useState를 순수한 자바스크립트 형태로 구현 한다면 이와 같은 구조(완벽한 구조는 아니지만)라고 할 수 있는데요.

이러한 useState를 사용하기 위해서는 선언된 스테이트의 상태(첫번째 할당)를 어떻게 반환할지 상태 관리 메서드(두번째 할당)에 작성 해주는 인라인 방식도 가능하고요.


const [counter, setCounter] = useState(0);

// 사용자가 버튼을 클릭할 시 counter를 관리하고 있는 setCounter 메서드를 이용해 해당 상태를 1 증가
<button className="button" onClick={() => {
    setCounter((prev) => prev + 1)
    cheking();}}>+</button>

다만 이러한 방식은 코드의 가독성을 저해하기에, 가급적 일반 함수 안에 해당 메서드를 호출하여 상태를 제어하는 방식을 사용합니다.


const [counter, setCounter] = useState(0);

// 해당 메서드를 호출하여 상태를 변경하는 함수를 작성
function plusButton() {
setCounter((prev) => prev + 1);
}

<button className="button" onClick={plusButton}>+</button>

이와 같이 일반 함수를 이용해 해당 상태 관리 메서드를 호출하는 것이 일반적인데요. 이와 같이 리액트에서는 일반 함수 자체에서 사용자가 임의로 지정한 변수나 메서드가 아닌, 리액트에서 제공해주는 useState로 각각의 상태를 관리하게 된답니다.

코드를 살펴보면 선언된 useState 훅스의 변수들을 구조 분해 할당으로 각각 countersetCounter 변수에 할당하는데요.

여기서 counter훅스로 관리하게 될, 변화되는 값을 의미하고 setCounter는 해당 상태를 관리하는 방법 (메서드) 가 됩니다. 즉 훅스는 일종의 상태와 그 상태를 제어하는 메서드로 이루어진 배열을 의미하는 것**이죠.

그리고 괄호 안에 들어가 있는 숫자 (0)는 해당 스테이트에 저장될 초기 상태를 의미합니다. 위의 코드에서는 counter의 초기값이 0으로 할당되어 초기화 되겠지요.

이때 스테이트를 제어하는 메서드 (setCounter)를 일반 함수에 감싸서 이벤트 핸들러로 전달하는 이유는 코드의 재사용, 유지 보수 및 디버깅의 경우 보다 유용한 구간 탐색과 사용이 가능하기에 위의 코드와 같이 전달을 하는 것입니다.

주의할 점은 하나의 훅스는 하나의 상태 및 제어 메서드만을 담당하며, 다수의 상태를 하나의 훅스로 관리하고자 한다면 해당 상태를 초기화 할 때 배열의 형태로 할당하여 배열의 특정 상태만 변경시키는 방법을 사용하면 됩니다.

import React, { useState } from 'react';

function Counter() {
  // 여러 상태를 객체로 관리합니다.
  const [state, setState] = useState({ counter1: 0, counter2: 0 });

  // 상태를 변경하는 함수들을 정의합니다.
  const incrementCounter1 = () => {
    setState((prevState) => ({
      ...prevState,
      counter1: prevState.counter1 + 1
    }));
  };

  const incrementCounter2 = () => {
    setState((prevState) => ({
      ...prevState, // 이전의 상태 값에
      counter2: prevState.counter2 + 1 // 변경할 속성 값을 새로 지정합니다.
    }));
  };

  return (
    <div>
      <p>Counter 1: {state.counter1}</p>
      <button className="button" onClick={incrementCounter1}>Increment Counter 1</button>

      <p>Counter 2: {state.counter2}</p>
      <button className="button" onClick={incrementCounter2}>Increment Counter 2</button>
    </div>
  );
}

export default Counter;

이 외에도 useState와 비슷한 방식의 훅스는 뒤에서 설명할 useReducer가 있겠습니다.

정리하자면 해당 컴포넌트의 상태를 변경 (리렌더링) 하기 위해서는 훅스를 이용해야 하며, 이럴 때 사용하는 보편적인 리액트 라이브러리인 훅스(Hooks)를 사용하게 됩니다.

profile
인생은 본인의 삶을 곱씹어보는 R과 타인의 삶을 배워 나아가는 L의 연속이다.

0개의 댓글