[퓨처라마] 퀴즈 만들기(함수형 업데이트, batch update)

✨ 퀴즈 만들기

이제 퓨처라마 퀴즈다. 객관식이며 문제는 총 28개이고 답안은 4개다. 정답을 맞춰야 다음 문제로 넘어갈 수 있도록 만들 것이다.

useState : 한 문제씩 가져오기

리액트에서 컴포넌트의 바뀌는 값을 관리하기 위해 useState 를 사용한다.
useState는 변수를 상태관리해주는 Hook이다. 함수에 초기 상태를 전달하면, 현재 상태값이 있는 변수와 이 변수를 업데이트하는 함수를 반환한다. 그래서 비구조화 할당을 통해 각 원소를 추출해준다. 출처: blog.logrocket.com

const [current, setCurrent] = useState(0);

우리는 지금 한 문제씩 가져와야하기 때문에, index값을 1씩 더해가며 넘겨줄 것이다.
초기값은 0으로 지정해서, 배열의 첫 번째 요소를 가져올 것이다.

// 아래처럼 업데이트할 값을 넣어주는 게 아니라
setCurrent(current+1)
// 값을 업데이트하는 함수를 넣어줌
setCurrent((current) => current + 1)

useState의 두 번째 원소는 매개변수로 전달 받은 값을 최신 상태로 설정해주는Setter 함수다. 정답을 맞출 때마다 index값이 바뀌어야하는 데, 이 때Setter함수에 업데이트할 을 넣어주는 것이 아니라 값을 업데이트하는 함수를 넣어줄 것이다.

함수형 업데이트 : useState의 비동기적 속성

case 1

다음 코드를 실행해보자.

const [count, setCount] = useState(0);

const onClick = () => {
    setCount(count + 1);
    console.log(count);
  };
  
<Button onClick={onClick}>{count}</Button>

버튼에 onClick 이벤트로 1씩 더해주는 setCount 함수를 붙였다.
버튼을 클릭하면 숫자, 그러니까 상태값은 올라가는데 console은 이전 상태값을 출력한다.
이는 useState 비동기적 속성과 관련있다. setState에서 상태를 업데이트하면 즉시 반영되는 게 아니라 리렌더링이 된 이후에 반영된다.

상태값 변경 -> 리렌더링 -> 상태값 업데이트
그래서 화면에서는 1이 더해졌지만 콘솔에는 그 이전 값이 출력되는 것이다.

case 2

다음 코드를 실행해보자.

const [count, setCount] = useState(0);

const onClick = () => {
  setCount(count+ 1);
  setCount(count+ 1);
  setCount(count+ 1);
}

<Button onClick={onClick}>{count}</Button>

3씩 더해질 것 같지만 1씩 더해지는 모습을 볼 수 있다.
앞서 말했지만 setState()는 비동기적으로 작동한다.

const [count, setCount] = useState(0);

const onClick = () => {
  setCount(count+ 1);
  setCount(count+ 2);
  setCount(count+ 3);
}

<Button onClick={onClick}>{count}</Button>
/// 3 맨 아래꺼만 실행

그래서 동일한 주기동안 여러 호출을 단일호출로 그룹화하고 일괄처리한다.
후속호출이 동일한 주기의 이전 호출값을 무시해버리는 것이다.
리액트는 왜 이렇게 만들었을까?

state batch updating

React may batch multiple setState() calls into a single update for performance.

React는 성능을 위해 여러 setState() 호출을 단일 업데이트로 한꺼번에 처리할 수 있습니다. 리액트 공식 문서

리액트 이벤트 핸들러의 업데이트에만 기본적으로 batch update가 적용된다. - Dan Abramov (Facebook React Core팀)

리액트에서 state가 변경될 때마다 한 번씩 리렌더링이 일어난다면 효율성이 많이 떨어질 것이다. 그래서 리액트에서는
여러 개의 state 값을 각각 업데이트하는 것이 아니라 한 번에 업데이트해서 리렌더링을 한 번만 발생시키는데, 이를 batch update라 한다.