ilokesto

setState

setState()는 저장된 값을 바꾸는 유일한 메서드입니다.

setState(nextState: T | ((prevState: T) => T)): void

이 메서드는 완전한 다음 값 또는 updater 함수를 받습니다. updater는 이전 상태를 받고 완전한 다음 상태를 반환해야 합니다.

완전한 값 전달하기

const statusStore = new Store({ status: "idle", error: null as string | null });

statusStore.setState({ status: "loading", error: null });

전달한 값은 전체 상태를 교체합니다. shallow merge도 deep merge도 없습니다.

updater 함수 전달하기

statusStore.setState((prev) => ({
  ...prev,
  status: "success",
}));

다음 값이 이전 값에 의존한다면 updater를 사용하세요. 배열, counter, map, 필드를 보존해야 하는 객체 상태에서 가장 안전한 패턴입니다.

알림 알고리즘

구현은 다음 순서로 상태를 계산합니다.

  1. 등록된 미들웨어 배열에서 middleware chain을 만듭니다.
  2. nextState 값 또는 updater로 chain을 실행합니다.
  3. 최종 단계에서 nextState가 함수라면 updater를 호출합니다.
  4. 이전 값과 계산된 값을 Object.is로 비교합니다.
  5. 같은 값 또는 같은 참조라면 알리지 않고 반환합니다.
  6. 다르면 계산된 값을 저장하고 구독자에게 알립니다.

병합이 아니라 교체

const store = new Store({ a: 1, b: 2 });

store.setState({ a: 2 });
console.log(store.getState()); // { a: 2 }

{ a: 2, b: 2 }를 기대했다면 이전 객체를 직접 복사해야 합니다.

store.setState((prev) => ({ ...prev, a: 2 }));

같은 참조는 알림이 없습니다

store.setState((prev) => prev);

prev를 그대로 반환하면 Object.is(prev, prev)가 true이므로 no-op입니다.

store.setState((prev) => {
  prev.a = 3;
  return prev;
});

이 mutation은 no-op보다 더 위험합니다. 객체는 바뀌었지만 참조가 같아서 구독자에게 알리지 않습니다. 객체 상태에서는 항상 새 객체나 새 배열을 반환하세요.

Error 처리

setState()는 미들웨어, updater 함수, 리스너에서 던진 error를 잡지 않습니다. 실패를 잡아야 하는지는 setState()를 호출하는 쪽에서 결정하세요.

목차