인프런 커뮤니티 질문&답변

ccct님의 프로필 이미지
ccct

작성한 질문수

처음 만난 리액트(React)

(실습) 클릭 이벤트 처리하기

이벤트 실행순서에 대해 질문드려요

작성

·

188

·

수정됨

1


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

function ConfirmButton2 (){
    
    const [isConfirmed,setIsconfirmed] = useState(false);
    const handleConfirm = ()=>{
        setIsconfirmed((prevIsConfirmed) => !prevIsConfirmed);
        // setIsconfirmed(!isConfirmed);
    };

    const [number, setNumber] = useState(0);
    const checkNumber =() =>{

        alert("첫번째 "+number); // 0 
        setNumber((prevnumber)=>{
            alert(prevnumber+"//"+number); // 0 0
            return prevnumber+10;
        });
        setNumber((prevnumber)=>{
            alert(prevnumber+"//"+number); // 10 0
            return prevnumber+10;
        });
        alert("두번째"+number); // 0 
    };

    return (
        <>
        <button onClick = {handleConfirm} >
                {isConfirmed ? "확인됨2" : "확인하기2"}
        </button>
        <button onClick = {checkNumber}>
            {number} 
        </button>
        </>
    );
    

};

export default ConfirmButton2;

이렇게 해서 실행을 하고 숫자 버튼을 클릭하면
첫번째 alert -> set함수 alert -> 두번째 alert -> 두번째 set함수 alert 
이 순서로 나오는데, 
alert ->  set 함수 alert -> 두번째 set함수 alert -> 두번째 alert 이 순서가 아닌 이유를 모르겠어요.

답변 2

0

Inje Lee (소플)님의 프로필 이미지
Inje Lee (소플)
지식공유자

안녕하세요, 소플입니다.

 

우선 리액트 컴포넌트에서 state의 업데이트는 조금 복잡한 과정을 거치게 됩니다.

일반적으로 리액트는 state 업데이트를 처리하기 전에 이벤트 핸들러의 모든 코드가 실행될 때까지 기다립니다.

그렇기 때문에 지금 겪으신 것처럼 작성한 코드의 순서대로 실행되지 않는 경우가 많습니다.

 

그리고 이러한 특징 때문에 state를 업데이트 할 때,

하나의 set함수를 하나의 이벤트 핸들러에서 동시에 호출하는 형태로는 코드를 작성하지 않는게 좋습니다.

 

추가로 아래 공식문서를 살펴보시면 조금 더 자세하게 이해하실 수 있을겁니다 😀

https://react.dev/learn/state-as-a-snapshot

https://react.dev/learn/queueing-a-series-of-state-updates

 

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다.

질문하신 이벤트 실행순서에 대한 현상은 React의 상태 업데이트 방식과 비동기적인 처리 때문입니다.

React에서 useState의 상태 업데이트 함수인 setNumber는 비동기적으로 작동합니다. 즉, setNumber를 호출하더라도 상태 값이 바로 변경되지 않고, 컴포넌트의 다음 렌더링 시점에 변경된 상태를 반영합니다. 따라서, 여러분이 작성하신 코드에서 alert("두번째"+number); 가 먼저 실행될 때는 아직 상태 값이 업데이트되기 전이기 때문에 초기 상태 값을 보여줍니다.

그리고 setNumber 함수 내부에서 사용된 콜백 함수는 이전 상태 값을 인자로 받아서 새로운 상태 값을 반환합니다. 이 콜백 함수는 바로 이전 상태를 기반으로 연산하기 때문에 연속된 setNumber 호출에서는 첫 번째 setNumber 호출에 의해 예정된 상태 변경을 기반으로 연산됩니다.

정리하자면, setNumber의 콜백에서 각각 다른 현재 상태를 기반으로 계산하게 되는데, 실제 상태 값의 변경은 비동기적으로 이루어지기 때문에 alert("두번째"+number);에서는 변경되기 전의 초기 상태 값을 보게 되는 것입니다.

이 특성 때문에 여러분이 경험한 것처럼 alert -> set 함수 alert -> 두번째 set함수 alert -> 두번째 alert 순서대로 출력되지 않는 현상이 발생합니다.

ccct님의 프로필 이미지
ccct

작성한 질문수

질문하기