[React] React의 setState와 비동기 처리

React에서 useState를 사용하여 상태(state)를 관리할 때, 간혹 상태 업데이트가 예상대로 이루어지지 않는 상황을 경험할 수 있습니다. 특히, setState가 비동기적으로 동작하는 점을 이해하는 것이 중요합니다. 이번 글에서는 이와 관련된 문제와 해결 방법에 대해 다루어 보겠습니다.

문제 상황

아래 코드는 useState를 사용하여 상태를 업데이트하고, 업데이트된 상태를 기반으로 API 호출을 시도하는 예제입니다.

const [a, setA] = useState(null); 

const settingA = () => { 
  setA(1);
  callAPI();
}

const callAPI = () => {
  console.log(a);
}

callAPI();

여기서 settingA 함수가 호출되면, 상태 a1로 업데이트되고, callAPI 함수가 호출되어 콘솔에 a의 값을 출력할 것으로 예상할 수 있습니다. 하지만 실제로 콘솔에 찍히는 값은 null입니다. 왜 그럴까요?

원인 분석

setState는 비동기적으로 동작합니다. 즉, setA(1)이 호출되더라도 즉시 상태가 업데이트되지 않으며, 리렌더링 이후에야 새로운 상태 값이 반영됩니다. 따라서 setA를 호출한 직후 callAPI를 호출하면 여전히 이전 상태 값을 참조하게 됩니다.

해결 방법

상태 업데이트 후 특정 작업을 수행하려면 useEffect 훅을 사용하는 것이 좋습니다. 상태 값이 변경될 때마다 그에 따라 필요한 작업을 수행하도록 할 수 있습니다. 다음은 이를 구현한 예제입니다.

import React, { useState, useEffect } from 'react';

const MyComponent = () => {
 const [a, setA] = useState(null);
 const [isSetA, setIsSetA] = useState(false);
 const settingA = () => {
    setA(1);
    setIsSetA(true);
  }
  useEffect(() => {
    if (isSetA) {
      callAPI();
    }
  }, [isSetA]);
  const callAPI = () => {
    console.log(a);
    setIsSetA(false);
  }
  return (
    <div>
      <button onClick={settingA}>Set A and Call API</button>
    </div>
  );
}

export default MyComponent;

개선된 방법

위 코드도 동작하긴 하지만, isSetA라는 추가적인 상태를 사용하지 않고 더 간단하게 해결할 수 있습니다. useEffect를 사용하여 상태 a가 변경될 때마다 callAPI를 호출하도록 합니다.

import React, { useState, useEffect } from 'react';

const MyComponent = () => {
  const [a, setA] = useState(null);
  const settingA = () => {
    setA(1);
  }
  useEffect(() => {
    if (a !== null) {
      callAPI();
    }
  }, [a]);
  const callAPI = () => {
    console.log(a);
  }

  return (
    <div>
      <button onClick={settingA}>Set A and Call API</button>
    </div>
  );
}

export default MyComponent;

이제 상태 a가 변경될 때마다 callAPI가 호출되며, 콘솔에 1이 출력될 것입니다.

마무리

React에서 상태 관리와 비동기 업데이트는 중요한 개념입니다. setState가 비동기적으로 동작함을 이해하고, useEffect를 활용하여 원하는 타이밍에 작업을 수행할 수 있도록 코드를 작성하는 것이 중요합니다. 이 글이 여러분의 개발에 도움이 되었길 바랍니다. 질문이나 더 나은 방법이 있다면 댓글로 공유해주세요!

읽어주셔서 감사합니다.

다음 내용이 궁금하다면?

또는

이미 회원이신가요?

2024년 6월 12일 오후 12:11

댓글 0

    함께 읽은 게시물

    📚 알아두면 좋은 ‘영어 개발 용어’ 11개

    프로그래밍에서 특정 단어는 영어의 사전적 의미와는 비슷하지만 다른 의미로 쓰입니다. 프로그래밍을 시작하신지 얼마 안되었다면 이런 단어들을 처음 봤을 때 사전적 의미 그대로 해석하여 혼란스러우실 수 있는데요. 알아두면 좋을 개발 영어 용어 11개를 가져왔습니다 :) --- "알아두면 좋은 영어 개발 용어" 1. Agnostic (사전적 의미: 불가지론의) ‘구애받지 않는 것’이라는 뜻을 가집니다. 대체로 어떤 것에 국한되지 않는 프로그램이나 기술을 표현할 때 사용됩니다. `Nestjs is platform-... 더 보기

    GitHub - meotitda/DICTIONARY: 📚한글-English 개발 사전

    GitHub

    GitHub - meotitda/DICTIONARY: 📚한글-English 개발 사전

     • 

    저장 204 • 조회 9,144


    난임 스타트업 '오키드헬스'는 배아를 대상으로 향후 발병 소지가 있는 수천 가지 질병을 검사하는 서비스를 제공한다. 이 서비스를 통해 예비 부모는 자녀의 유전 정보를 이전보다 훨씬 더 많이 알 수 있다.

    ... 더 보기

    유전 데이터로 아기 선별해 낳는다?…美 스타트업 '슈퍼베이비' 논란

    n.news.naver.com

    유전 데이터로 아기 선별해 낳는다?…美 스타트업 '슈퍼베이비' 논란

    조회 194



    🧭 우리만의 디자인 시스템, 어디서부터 시작할까?

    ... 더 보기

    우리만의 디자인 시스템, 어디서부터 시작할까? · DaleStudy/daleui · Discussion #392

    GitHub

    우리만의 디자인 시스템, 어디서부터 시작할까? · DaleStudy/daleui · Discussion #392

    클로드 코드 Max 한 달 사용 후기

    ... 더 보기

    클로드 코드 한 달 사용 후기

    K리그 프로그래머

    클로드 코드 한 달 사용 후기

     • 

    댓글 2 • 저장 7 • 조회 2,268


    AI들 코딩 스타일이, GPT는 구글같고, Claude는 메타같음. Gemini는 부트캠프..🫢


    그래서 응용레벨 코딩에는 Claude가 낫고, 로우레벨 코딩에는 GPT가 나은 편.


    * 당연하지만 개인적인 느낌일 뿐 입니다.