useState 사용 이유

Han Lee·2024년 2월 1일

함수형 컴포넌트에서 App의 상태(state) 업데이트 하기 위해 useState 사용한다.

P1. useState 사용 이유

1. Re-Rendering

  • React에서 함수형 컴포넌트를 사용해 최초 렌더링을 진행한 이후, React 사용하지 않는 JavaScript 방식에서와 같이 변수를 업데이트 진행한 경우, 개발자가 생각한 기대와 다르게 작동되는 경우가 있다.
  • 즉, 개발자는 기존의 방법을 사용하여 변수를 업데이트를 진행하고, 업데이트된 변수에 따라 Re-Rendering 될 것을 예상하지만 React의 함수형 컴포넌트에서 예상과 다르게 Re-Rendering이 진행되지 않는다.
  • 그리고 바로 이러한 상황에서 개발자는 useState를 사용해야 한다.

2. Code Example

(1) JavaScript / Re-Rendering ( Yes )

let countState = 0;
const appCountElement = document.getElementById('app-count');
const appCountBtnElement = document.getElementById('app-btn');

const handleClick = () => {
  console.log('Click Event');
  countState++;
  appCountElement.textContent = countState;
};

appCountBtnElement.addEventListener('click', handleClick);

(2) React / Re-Rendering ( No )

function Counter() {
  let count = 0;

  const handleClick = () => {
    console.log("Click Event");
    count++;
  };

  return (
    <>
      <h1>React</h1>
      <h2>Count</h2>
      <div>{count}</div>
      <button onClick={handleClick}>Up</button>
    </>
  );
}

export default Counter;

P2. useState 사용 예시

1. useState 사용

  • 리액트에서 리렌더링은 함수형 컴포넌트의 return 함수를 실행한 다음, 해당 실행 결과물을 이전의 리액트 트리와 비교한다.
  • 비교하는 과정에서 리-렌더링이 필요한 부분만 업데이트가 발생한다.
  • 따라서, useState 반환 값의 두번째 원소인 setState 함수를 사용해 state 값을 변경하는 경우 리-렌더링이 발생하게 된다.

2. Code Example

  • 다음의 예시를 통해, 함수형 컴포넌트의 return 문을 통해 반환된 결과물을 가지고 서로 비교하여, Re-Render Process가 발생하는 것을 알 수 있다.

(1) useState 미사용

function Test() {
  let state = 'Hello';

  function handleBtnClick() {
    console.log('Click Event');
    state = '안녕';
    
  }

  return (
    <div>
      <h1>Use State</h1>
      <h2>{state}</h2>
      <button onClick={handleBtnClick}>한글</button>
      {console.log('return - state:', state)}
    </div>
  );
}

export default Test;

( "한글" 버튼을 아무리 클릭해도, return 문의 {state} 값은 초기화 값 "Hello" 이다. )

(2) useState 사용

import { useState } from 'react';

function Test() {
  const [state, setState] = useState('Hello');

  function handleBtnClick() {
    console.log('Click Event');
    setState('안녕');
  }

  return (
    <div>
      <h1>Use State</h1>
      <h2>{state}</h2>
      <button onClick={handleBtnClick}>한글</button>
      {console.log('return - state:', state)}
    </div>
  );
}

export default Test;

( "한글" 버튼을 클릭하면, state 값이 변경되어 리-렌더링 된다. )

P3. useState 사용 유의점

1. Object 업데이트 방법

  • JavaScript number, string 등의 원시타입은 불변성(immutable)을 갖기 때문에, setState 함수를 호출하여, 해당 값(value)을 업데이트하면 된다.
  • 반면, JavaScirpt Object 타입은 가변성(mutable)을 갖는다고 할지라도, 원시타입과 같이 불변성(immutable)을 갖고 있다고 취급해야 한다.
  • 즉, 객체의 값을 바꾸려(mutable)하지 말고 교체(replace)를 해야 React는 state가 변경된 것을 인식하고 Re-Rendering 된다.

2. Code Example

(1) Mutable ( Wrong Example )

import { useState } from 'react';

function Test() {
  const [state, setState] = useState({ name: 'Han', greeting: 'Hello' });

  function handleBtnClick() {
    console.log('Click Event');
    setState((state.greeting = '안녕'));
  }

  return (
    <div>
      <h1>Use State</h1>
      <h2>
        {state.greeting} {state.name}
      </h2>
      <button onClick={handleBtnClick}>한글</button>
      {console.log(state)}
    </div>
  );
}

export default Test;

(2) Im-Mutable ( Right Example )

import { useState } from 'react';

function Test() {
  const [state, setState] = useState({ name: 'Han', greeting: 'Hello' });

  function handleBtnClick() {
    console.log('Click Event');
    setState({...state, greeting: "안녕"});
  }

  return (
    <div>
      <h1>Use State</h1>
      <h2>
        {state.greeting} {state.name}
      </h2>
      <button onClick={handleBtnClick}>한글</button>
      {console.log(state)}
    </div>
  );
}

export default Test;

0개의 댓글