
// This is a React Quiz from BFE.dev
import * as React from 'react'
import { useState } from 'react'
import { createRoot } from "react-dom/client";
import { screen, fireEvent } from "@testing-library/dom"
function App() {
const [state, setState] = useState(0)
const increment = () => {
setTimeout(() => {
setState(state + 1)
}, 100)
}
console.log(state)
return <div>
<button onClick={increment}>click me</button>
</div>
}
const root = createRoot(document.getElementById('root'))
root.render(<App/>)
;(async () => {
const action = await screen.findByText('click me')
// click the button twice
fireEvent.click(action)
await wait(50);
fireEvent.click(action)
await wait(50);
})()
function wait(duration = 100) {
return new Promise((resolve) => setTimeout(resolve, duration));
}
0
1
1
0 출력: App이 처음 실행될 때 state는 0입니다.
첫번째 클릭 (t = 0ms): setTimeout이 예약됩니다. 이 타이머 안의 콜백 함수는 생성 당시의 state인 0을 가지고 있습니다.
두 번째 클릭 (t = 50ms): 두 번째로 실행된 increment 내부의 타이머도 동일하게 생성 당시의 state인 0을 가집니다.
1 출력: 첫 번째 타이머가 종료되면서 setState(0 + 1)을 실행합니다.1 출력: 두 번째 타이머가 종료되면서 setState(0 + 1)을 실행합니다.✨
increment함수가 선언될 때의state값(0)을setTimeout이 그대로 가져갔기 때문에state값이2가 되지 않습니다
🤔 만약 2로 만들고 싶다면?
함수형 업데이트(Updater function)를 사용해야 합니다.
// 기존 방식 (문제 발생) setState(state + 1) // 해결 방식 (항상 최신 상태 참조) setState(prevState => prevState + 1)