반응형 상태의 기본

읽는 시간 약 10

이 문서에서 배우는 것

  • 반응형 값을 만들고 읽고 쓰는 법
  • 갱신 범위가 어떻게 정해지는지
  • 상태를 어디에 두어야 하는지

값 만들기

state()는 읽기 함수를 돌려줍니다. 괄호를 붙이면 현재 값을 읽고, .set()으로 새 값을 씁니다. 이 두 가지가 전부입니다.

import { state } from 'loopkit';

const count = state(0);
count();          // 0
count.set(1);
count();          // 1

왜 화면이 따라오는가

템플릿 안에서 count()를 읽는 순간, 런타임은 “이 자리가 이 값을 본다”고 기록해 둡니다. 나중에 count.set()이 호출되면 기록해 둔 자리만 다시 계산합니다. 컴포넌트 전체를 다시 실행하지 않기 때문에, 큰 화면에서도 갱신 비용이 값을 실제로 쓰는 지점 수에 비례합니다.

function Counter() {
  const count = state(0);
  return html`
    <p>지금까지 ${count()}번</p>
    <button @click=${() => count.set(count() + 1)}>하나 더</button>
  `;
}

참고

컴포넌트 함수는 마운트 시점에 한 번만 실행됩니다. 그래서 state()를 함수 본문 맨 위에 두어도 매번 초기화되지 않습니다.

상태를 어디에 둘까

한 컴포넌트만 쓰는 값이면 그 안에 둡니다. 두 컴포넌트가 같은 값을 봐야 하면, 둘의 가장 가까운 공통 부모로 올리고 인자로 내려 줍니다. 앱 전체가 봐야 하는 값이라면 모듈 최상단에 두고 필요한 곳에서 import 해도 됩니다. 루프킷의 상태는 컴포넌트 트리에 묶여 있지 않기 때문에, 전역 상태를 위해 별도 저장소 라이브러리를 얹을 필요가 거의 없습니다.

// session.js
export const user = state(null);

주의

객체를 상태에 담고 속성만 바꾸면 갱신이 일어나지 않습니다. .set()에 새 객체를 넘기거나, 처음부터 필드별로 상태를 나누세요.

요약

  • state()는 읽기 함수 + .set() 조합이다.
  • 읽는 지점만 기록되고, 그 지점만 다시 계산된다.
  • 상태는 트리에 묶이지 않아 모듈 수준 전역으로도 쓸 수 있다.