본문 바로가기

Develop Log/React

React - useState()를 알아보자

반응형

React - useState()

useState()는 React를 처음 접하게 되면 가장 먼저 접하게 되는 hook 중 하나라고 생각한다

가장 간단한 설명으로는 상태를 저장하여 관리할 수 있는 hook이라고 알고 있지만 useState가 어떤 식으로 동작하는지, 어떻게 상태를 관리하는지는 자세하게 알아보려고 하지 않았던 것 같다

그래서 이번기회에 useState()가 정확하게 어떤건지, 어떤 역할을 하고 어떻게 구성이 되어있으며 react 컴포넌트에서 어떻게 동작하는지 알아보려고 한다

useState()

  • useState는 React 컴포넌트에서 상태 관리를 위해 사용되는 Hook이다
  • 이 hook을 사용하게 되면 함수형 컴포넌트 내에서도 상태를 가질 수 있게 되어 더욱 선언적이고 가독성 있는 코드 작성이 가능해진다

구성

useState()는 하나의 상태값을 관리하며, 초기 상태값을 인자로 받아 두 가지 값을 배열로 반환한다

const [    state   ,           setState        ] = useState(initialState);
const ['↑↑현재 값↑↑', '↑↑상태를 업데이트하는 함수↑↑'] = useState('초기값')

이렇게 함수를 통해 상태를 업데이트하는 방식은 직접적인 변이를 피하고 새로운 상태값을 대체하는 불변성 원칙을 따른다

동작 원리

  1. React의 컴포넌트가 렌더링 될 때마다 useState()는 상태값을 메모리에서 읽어온다
  2. useState()는 전달된 초기 상태값을 첫 번째 렌더링에서만 사용한다 이후에 렌더링에서는 현재 상태값을 반환한다
  3. 상태를 업데이트하는 함수가 호출되면 이 함수는 새로운 상태값을 인자로 받게 된다
  4. 새로운 상태값을 기반으로 React는 컴포넌트를 업데이트(리렌더링) 한다
  5. 이때 useState()는 이전에 메모리에 저장한 상태값 대신 새로운 상태값을 반환한다

컴포넌트가 업데이트 된 후 새로 상태값을 지정하는 함수가 실행되는 것이 아닌 상태값을 변경하는 함수가 실행된 뒤 컴포넌트가 업데이트 되는걸 기억해야 한다

이러한 방식으로 useState()는 함수형 컴포넌트에서 상태 관리를 가능하게 하고 컴포넌트의 렌더링 사이에 상태값을 유지하게 된다

사용 목적

사용 이유

  1. 상태 관리: 함수형 컴포넌트에서 로컬 상태를 가질 수 있게 해 주며 이는 컴포넌트의 동적 데이터를 관리하는데 필요하다
  2. 재사용성: 함수형 컴포넌트와 훅을 사용하면 코드의 재사용성이 증가하고, 테스트와 디버깅이 쉬워진다

사용 시 주의사항

  1. Top Level에서만 호출: hook은 함수 컴포넌트의 최상위 레벨에서만 호출되어야 한다 반복문, 조건문 또는 중첩된 함수 내에서 hook을 호출하면 안 되는데 왜냐하면 함수형 컴포넌트의 hook이 컴포넌트의 렌더링 순서에 따라 호출되는 것을 보장해야 하기 때문이다
  2. 함수 컴포넌트와 Custom Hook 내에서만 호출: useState와 같은 hook은 React 함수 컴포넌트 내부 또는 사용자 정의 hook 내에서만 호출되어야 한다 일반적인 JavaScript 함수에서는 호출되지 않아야 합니다.
  3. Immutable Updates: useState 훅을 사용할 때 상태를 직접 변경(mutate)하면 안 되며 새로운 상태 객체를 만들어서 이를 사용해야 한다 이는 React가 상태의 변화를 감지하고 컴포넌트를 재렌더링하는 데 필요하기 때문이다
  4. 비동기 업데이트: React의 상태 업데이트는 비동기적으로 일어나므로, 여러 상태 업데이트가 일어날 때 이전 상태 값을 기반으로 계산하는 것에 주의해야 합니다. 이때는 함수형 업데이트를 사용해야 합니다.

예제

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); 

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}> // setCount를 통해 count 상태 업데이트
        Click me
      </button>
    </div>
  );
}

export default Counter;
  1. 위 코드에서 useState(0)을 호출하면, count라는 상태 변수가 생성되며 초기 값은 0이 된다
  2. 두 번째로 상태를 변경할 수 있는 setCount 함수가 반환된다
  3. 버튼을 클릭하면, setCount가 호출되어 count 상태가 증가하게 된다
  4. setCount 함수가 호출되면 해당 컴포넌트는 리렌더링 되며, 새로운 count 상태를 반영하여 화면에 보여줍니다.
  5. 이처럼 useState는 리액트 컴포넌트에서 상태를 관리하고 업데이트하는 데 사용됩니다.

실전에서 사용할 때

import { useState } from 'react';

export default function Counter() {
  const [name, setName] = useState('Mike');

  function handleClick() {
     setName('Robin');
     console.log(name); // 여기에 찍히는건 Mike일까 Robin일까
  }

  return (
      <>
          <h1>{name}</h1>
          <button onClick={handleClick}>
      </>

  );
}

버튼을 클릭하면 이름이 Mike에서 Robin이 되는 것인데 쉽게 생각해 본다면 name의 상태를 Robin으로 변경해 주었기 때문에 로그에 찍히는 name값은 Robin이 될 것 같지만 전혀 그렇지 않다

로그에는 여전히 Mike가 찍힐 것이다

이렇게 보았을 때 업데이트가 되는 부분을 순서로 나열해 보면

  1. 클릭 이벤트가 발생하여 handleClick()이 실행이 된다
  2. handleClick()함수 내에 setName()이 실행된다

여기서부터가 중요한 부분이라고 생각되는데 절대로 setName()을 실행했다고 해서 바로 name의 값이 바뀌는게 아니다

  1. 이미 컴포넌트는 처음 렌더링될 때 값을 가지고 있기 때문에 로그에는 Mike가 찍히게 된다
  2. 이후 setName()으로 변경된 상태를 업데이트하기 위해서 컴포넌트를 다시 렌더링 한다
  3. 다시 렌더링이 되었을 때 새롭게 변경된 상태가 적용이 된다
반응형