[황준일]Vanilla Javascript로 React useState hook 만들기를 읽은 후기

jaemin·2023년 5월 3일
0

컴포넌트가 여러 개일 때 useState 만들기

let currentStateKey = 0;
const states = [];

function useState(initialState) {
  const key = currentStateKey;

  if (states.length === currentStateKey) {
    states.push(initialState);
  }

  const state = states[key];

  const setState = newState => {
    states[key] = newState;
    render();
  };

  currentStateKey += 1;

  return [state, setState];
}

function Counter() {
  const [count, setCount] = useState(1);

  window.increment = () => setCount(count + 1);

  return `
    <div>
      <strong>count: ${count}</strong>
      <button>증가</button>
    </div>
  `;
}

function Cat() {
  const [cat, setCat] = useState('고양이');

  window.meow = () => setCat(cat + '야옹!');

  return `
    <div>
      <strong>${cat}</strong>
      <button>고양이의 울음소리</button>
    </div>
  `;
}

function render() {
  const $app = document.querySelector('#app');

  $app.innerHTML = `
    <div>
      ${Counter()}
      ${Cat()}
    </div>
  `;

  currentStateKey = 0;
}

render();

블로그 글에 생략된 코드가 있어 이해에 어려움이 있었다. 블로그 본문에는 useState 함수 내부에 const key = currentStateKey 선언부가 빠져있었다. 이 부분이 빠지게 되면 currentStateKey는 계속 0을 가리키게 되고 Cat에서 setState를 사용하더라도 Counter의 상태가 변경되게 된다.

하지만, useState 내부에 currentStateKey를 변수에 복사하게 되면, 다르게 동작한다. 현재 currentStateKey 값이 아닌, 컴포넌트가 처음 호출될 때 당시의 currentStateKey 값을 기억하고 사용하므로 정확하게 상태를 변경할 수 있다.

requestAnimationFrame은 태스크 큐에 들어가는가?

requestAnimationFramesetTimeout이나 setInterval과는 다르게 현재 디스플레이 환경에 맞춰 최적의 빈도로 실행한다. 내가 알고 있는 큐는 task queue와 micro task queue가 있는데, requestAnimationFrame은 어디에 속하기에 최적의 빈도로 실행되는 것일까.

일반적으로 이벤트 루프가 콜스택에 무엇을 넣어 처리할지 결정할때, microtask를 가장 먼저 처리한다고 한다. microtask로는 promise 등이 속한다. 또, setTimeout이나 setInterval 같은 timer 함수는 task queue에 속한다.
microtask queue를 처리한 후에는 animation frame에 속하는 연산을 처리한다고 한다. 그러니까, queue는 microtasck queue, task queue, animation frame 이렇게 세 가지가 있는 것이다.
하지만 때로는 task queue에 있는 작업을 먼저 수행하기도 한다. 우선 순위는 animation frame이 먼저이지만, 초당 60프레임(혹은 주사율에 맞는)으로 보여주는 상황을 잘 충족하고 있다면 우선 순위를 task queue에게 양보하기도 한다.

profile
프론트엔드 개발자가 되기 위해 공부 중입니다.

0개의 댓글