코드를 작성하다가 내가 생각한 값이랑 실제 값이랑 다른 경우를 봤을 것이다. 이는 흔히 발생하는 문제이고 원인을 제대로 파악하지 못하면 더 나은 개발자로 성장할 수 없다.
해결한 코드
setState가 비동기이기 때문에 새로운 변수를 선언하고 이 변수를 함수에 넣어서 사용한다.
useState는 비동기 함수이다.
비동기란 특정 코드가 끝날때 까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 것을 의미한다.
이유
하나의 페이지나 컴포넌트 내에도 수많은 상태값이 존재한다. 만약 이 상태 하나하나가 바뀔 때마다 화면을 리렌더링 한다면 문제가 생길수도 있다.
때문에 리액트는 성능의 향상을 위해서 setState를 연속 호출하면 배치 처리하여 한 번에 렌더링하도록 하였다. 아무리 많은 setState가 연속적으로 사용되었어도 배치 처리에 의해서 한 번의 렌더링으로 최신 상태를 유지하는 것이다.
배치란? (batch)
배치란 React가 너 나은 성능을 위해 여러개의 state 업데이트를 하나의 리렌더링으로 묶는 것을 의미한다.
React는 16ms 동안 변경된 상태 값들을 하나로 묶는다. (16ms 단위로 배치를 진행한다.)
useState in React module
이제 useState가 왜 비동기로 동작하는지 알았다. 하지만 뭔가 조금 아쉬워서 React의 코드를 뜯어보았다.
React의 useState 함수이다. 이 함수는 resolveDispatcher라는 함수가 반환하는 객체의 useState라는 메서드를 실행하여 반환되는 값을 리턴한다.
그럼 이제 resolveDispatcher를 살펴보자.
resolveDispatcher 함수는 다시 ReactCurrentDispathcer라는 객체의 current 속성을 반환한다.
즉 useState는 ReactCurrentDispatcher 객체의 useState 메서드를 실행시키는 것이다.
이때 주목할 점은 ReactCurrentDispatcher가 객체라는 점이다.
객체이기 때문에 동일한 key 값에 대하여 이전의 값을 계속해서 덮어쓴다. 결국에는 마지막 명령어만 수행되는 셈이다. 아래처럼.
출처 https://garve32.tistory.com/m/39
그럼 useState를 동기적으로 처리하려면?
useState를 동기적으로 처리하는 방법은 지금 생각나는 것은 2가지가 있다.
첫 번째로는, useEffeect의 의존성 배열을 이용하는 것이다.
두 번째로는, setState의 인자로 함수를 집어넣는 것이다.
이렇게 setState의 인자로 함수를 집어넣으면 동기적으로 동작하는 것을 확인할 수 있다.
( setState내 함수의 매개변수로 이전 상태가 들어온다. )
결론
- useState는 비동기적으로 동작하는 훅이다.
- 비동기적으로 동작하는 이유는 성능 최적화 때문이다.
- 리액트는 성능을 최적화하기 위해 setState를 배치 처리한다.
- useState를 동기적으로 처리하려면 인자로 함수를 집어넣거나 useEffect의 의존성 배열을 활용하면 된다.
'JAVASCRIPT' 카테고리의 다른 글
!! 의 기능 (0) | 2024.06.03 |
---|---|
[Javascript] 객체를 나열하는 방법. (map함수 사용) (0) | 2024.01.12 |