버튼을 누를 때마다 6씩 증가해야하는데 1씩 증가한다.
import React, { useState } from "react"; export default function App() { const [count, setCount] = useState(0); const handleButton = () => { setCount(count + 2); setCount(count + 3); setCount(count + 1); }; return ( <div> <p>You clicked {count} times</p> <button onClick={handleButton}>Click me</button> </div> ); }
React는 퍼포먼스 향상을 위해 특별한 배치프로세스를 사용하기 때문이다.
여러 setState 업데이트를 한번에 묶어서 처리한 후마지막 값
을 통해 state를 결정하는 방식이다.
setCount()의 파라미터에 콜백 함수를 사용한다.
import React, { useState } from "react"; export default function App() { const [count, setCount] = useState(0); const handleButton = () => { setCount((prevCount) => prevCount + 1); setCount((prevCount) => prevCount + 1); setCount((prevCount) => prevCount + 1); }; return ( <div> <p>You clicked {count} times</p> <button onClick={handleButton}>Click me</button> </div> ); }
{ memoizedState: 0, // first hook baseState: 0, queue: { /* ... */ }, baseUpdate: null, next: { // second hook memoizedState: false, baseState: false, queue: { /* ... */ }, baseUpdate: null, next: { // third hook memoizedState: { tag: 192, create: () => {}, destory: undefined, deps: [0, false], next: { /* ... */ } }, baseState: null, queue: null, baseUpdate: null, next: null } } }
위 코드는 실제 hook을 변수에 할당하여 출력했을 때 나타나는 결과이다.
next는 연결리스트의 일종으로, 한 컴포넌트 안에서 여러번의 실행되는 hook들을 연결해주는 역할이다.
{ memoizedState: 0, baseState: 0, queue: { last: { expirationTime: 1073741823, suspenseConfig: null, action: 1, // setCount를 통해 설정한 값 eagerReducer: basicStateReducer(state, action), eagerState: 1, // 상태 업데이트를 마치고 실제 렌더링되는 값 next: { /* ... */ }, priority: 98 }, dispatch: dispatchAction.bind(bull, currenctlyRenderingFiber$1, queue), lastRenderedReducer: basicStateReducer(state, action), lastRenderedState: 0, }, baseUpdate: null, next: null }
React의 배치 프로세스는 이렇게 묶인 hook을 한번에 처리한 뒤 last를 생성한다.
여기서 주목할 부분은 최종 반환될 상태인 eagerState를 계산하는 함수가 Reducer라는 것이다.
function basicStateReducer(state, action) { return typeof action === 'function' ? action(state) : action; }
이 Reducer에 넘기는 action 타입이 함수일 때 이전 상태를 인자로 받는다.
그렇기 때문에 기존 상태를 기반으로 새로운 상태를 업데이트할 수 있게된다.
useState 모듈 분석