
// This is a React Quiz from BFE.dev
import * as React from 'react'
import { useState, useEffect, useLayoutEffect} from 'react'
import { createRoot } from 'react-dom/client'
function App() {
console.log('App')
const [state, setState] = useState(0)
useEffect(() => {
setState(state => state + 1)
}, [])
useEffect(() => {
console.log('useEffect 1')
return () => {
console.log('useEffect 1 cleanup')
}
}, [state])
useEffect(() => {
console.log('useEffect 2')
return () => {
console.log('useEffect 2 cleanup')
}
}, [state])
useLayoutEffect(() => {
console.log('useLayoutEffect')
return () => {
console.log('useLayoutEffect cleanup')
}
}, [state])
return null
}
const root = createRoot(document.getElementById('root'));
root.render(<App/>)
"App"
"useLayoutEffect"
"useEffect 1"
"useEffect 2"
"App"
"useLayoutEffect cleanup"
"useLayoutEffect"
"useEffect 1 cleanup"
"useEffect 2 cleanup"
"useEffect 1"
"useEffect 2"
App 출력: root.render(<App/>)에 의해 App 컴포넌트가 호출됩니다.
useLayoutEffect 출력: 화면이 그려지기 직전, 동기적으로 실행됩니다.
useEffect 1, useEffect 2 출력: 브라우저가 화면을 그린 후 비동기적으로 실행됩니다.
✨
useEffect의 의존성 배열에 값이 들어있더라도, 모든useEffect는 컴포넌트가 처음 나타날 때(Mount) 무조건 한 번은 실행됩니다.
App 출력: 새로운 state 값으로 렌더링합니다.
useLayoutEffect cleanup 출력: 새로운 레이아웃 효과를 적용하기 전, 이전 렌더링의 정리 함수를 먼저 실행합니다.
useLayoutEffect 출력: 새로운 state에 대한 레이아웃 효과가 실행됩니다.
useEffect 1 cleanup, useEffect 2 cleanup 출력: 화면이 그려진 후, 이전 렌더링의 useEffect들을 등록된 순서대로 모두 먼저 정리합니다.
✨ React는 새로운 효과를 실행하기 전, 이전 렌더링의 흔적을 지우기 위해 Cleanup을 먼저 수행합니다.
모든 Cleanup을 한꺼번에 모아서 처리한 후, 모든 새로운 이펙트를 한꺼번에 실행하여 일관성을 유지합니다.
useEffect 1, useEffect 2 출력: 모든 정리가 끝난 깨끗한 상태에서, 새로운 state에 대한 효과들을 순서대로 실행합니다.