티스토리 뷰

1. setState()에 async / await이 동작할까 ??

  • ✅ 결론은 setState()에서는 async / await을 사용해도 동작하지 않습니다.

  • JS에서는 일반적으로 코드를 동기방식으로 처리합니다. (코드 순서대로 위에서 아래로 차례대로 실행)
  • 예외적으로 callback 함수, ajax, setTimeout .. 등과 같은 함수들은 순차적으로 실행되지 않고 완료되면 실행됩니다. 이를 비동기적으로 처리한다고 정의합니다. (완료되는 순서대로 일을 처리하여 실행 순서가 확실하지 않음)
  • 비동기 함수를 동기방식으로 처리하려면 async / await 키워드를 사용합니다.
    await 문은 Promise가 fulfilled(이행) 되거나 rejected(거부) 될 때까지 async함수의 실행을 일시 정지하고, Promise 응답을 받으면 async함수를 일시 정지한 부분부터 실행합니다.

   1-1. React의 setState 함수는 동기, 비동기 어떤 방식으로 처리가 될까요?

  • ✅ 바로 비동기 방식으로 처리됩니다.

 

   1-2. setState()가 정말로 비동기 방식으로 처리되는지 예제를 보시겠습니다.

 

클래스형 컴포넌트에서 setState
함수형 컴포넌트에서 useState

  • 버튼을 클릭하면 onBtnEvent()라는 함수를 호출하고 해당 버튼을 3번까지만 클릭했을 때 현재 몇 번 클릭했는지 콘솔 창에 띄워주도록 했습니다.
  • setState()가 동기 방식으로 처리됐다면 콘솔 창에는

    1 클릭했습니다.
    2 클릭했습니다.
    3 클릭했습니다.

    3번의 로그가 찍혔을 것이기 때문에 setState()는 비동기 방식으로 처리된다는 걸 확인할 수 있습니다.

 

   1-3. setState()를 async / await 키워드를 통해 동기방식으로 처리한다면?

 

async / await은 Promise기반 키워드입니다. 하지만 setState()는 return value 가 없습니다.(Promise를 리턴하지 않습니다.)

결론적으로 setState()는 Promise를 반환하지 않기 때문에 await과 함께 사용할 수 없습니다.

 

클래스형 컴포넌트에서 async/await을 통한 setState
함수형 컴포넌트에서 async / await을 통한 useState

  • 그런데.. 클래스형 컴포넌트에서는 동기 처리가 잘 됩니다..? / 동기처럼 작동하는 것처럼 보입니다.
바벨(babel) 때문 ! 

바벨에서 async / await은 async 키워드는 generator, awiat 키워드는 yield에 대응됩니다. 하나의 로직이 종료될 때마다 이터레이터 객체 메서드인 next를 호출하여 다음 로직을 수행합니다.

✅ 따라서 바벨에 의해 마치 setState가 동기처럼 작동하는 것처럼 보이게 된 것입니다.

* 함수형 컴포넌트의 useStatae는 hook의 Stale Closure 문제가 발생하기 때문에 동기처럼 동작하지 않습니다.

* generator, yield, Stale Closure와 관련된 내용은 블로그 글을 작성해봐야겠다 !

2. setState() 동기 처리 방법

   2-1. 클래스형 컴포넌트

 

  • Promise 객체를 만들어 호출하기 !

 

  • 콜백 함수로 로직 전개하기 !

 

   2-2. 함수형 컴포넌트

 

  • useEffect 사용하기 !

 

🤔  정리 !

  • setState에 async / await 은 동작하지 않는다 !
  • 따라서 바뀐 state 값을 바로 사용하기 위해서는 (즉, 바뀐 state 값을 바로 접근하여 동적으로 쓰고자한다면)  클래스형, 함수형에서 처리하는 방법이 다르니 유의하자 !
  • 이번 포스팅을 위해 공부를 하면서 부족한 개념들(generator, yield, Stale Closure)에 대해 공부할 수 있어 좋았고, 공부한 내용을 따로 작성해봐야겠다 !

 

 

🔗 참고한 글

 

React의 setState에 await을 붙이면?

React의 setState에 await을 붙이면?

zigsong.github.io

댓글