업데이트 시맨틱
상태 업데이트 처리 방식과 알림이 트리거되는 시기입니다.
@ilokesto/store의 상태 업데이트는 예측 가능성과 성능을 보장하기 위해 엄격한 규칙을 따릅니다.
교체 시맨틱 (Replacement Semantics)
setState는 얕은 병합(shallow merge)을 수행하지 않습니다. 새로운 객체를 제공하면 전체 상태 원자(atom)를 교체합니다.
const store = new Store({ a: 1, b: 2 });
// 잘못된 예: 'b' 필드가 소실됨
store.setState({ a: 10 });
// 최종 상태: { a: 10 }
// 올바른 예: 필드 유지
store.setState((prev) => ({ ...prev, a: 10 }));
// 최종 상태: { a: 10, b: 2 }업데이트 함수 형태 (Updater Form)
현재 상태를 기반으로 다음 상태를 계산해야 할 때는 함수형 업데이트 형태 (prevState) => nextState를 사용하는 것이 가장 안전합니다.
store.setState((prev) => {
// prev를 기반으로 한 로직
return { ...prev, count: prev.count + 1 };
});불변성 패턴 (Immutable Patterns)
상태를 항상 불변하는 것으로 취급하십시오. getState()가 반환한 객체를 직접 수정하면 알림이 트리거되지 않으며 버그가 발생할 수 있습니다.
// 안티 패턴: 상태 직접 수정
const state = store.getState();
state.count = 100; // 리스너를 트리거하지 않음대신 업데이트를 트리거하려면 항상 새로운 객체 참조를 반환하십시오.
동일 참조 베일아웃 (Same-reference Bailout)
성능 최적화를 위해 Store는 Object.is를 사용하여 이전 상태와 새 상태를 비교합니다. 두 상태가 동일한 참조인 경우 업데이트가 무시됩니다:
- 내부 상태가 교체되지 않습니다.
- 리스너에게 알림이 가지 않습니다.
이를 통해 변경이 필요 없는 경우 업데이트를 안전하게 취소할 수 있습니다.
store.setState((prev) => {
if (noChangeNeeded) return prev; // 베일아웃 (취소)
return { ...prev, changed: true };
});함수 값 상태 주의사항
setState는 인자가 함수인지 확인하여 업데이트 함수로 처리할지 결정합니다. 따라서 함수를 루트 상태 값으로 쉽게 저장할 수 없습니다.
// 이는 다음 상태가 아니라 업데이트 함수로 처리됩니다
store.setState(() => console.log("Hello"));함수를 저장해야 하는 경우 객체로 감싸십시오: { fn: () => void }.
상태 형태 가이드
- 평평한(Flat) 구조가 좋습니다: 깊게 중첩된 상태는 불변 업데이트를 번거롭고 실수하기 쉽게 만듭니다.
- 직렬화 가능성: 코어 스토어에서 엄격하게 요구하는 것은 아니지만, 상태를 직렬화 가능한 POJO로 유지하면 나중에 퍼시스턴스나 개발자 도구를 추가하기 쉬워집니다.
- 원자성: 항상 같이 업데이트되는 관련 값들은 함께 묶어두십시오.