restate / v1.0.0

필요한 것만 구독하기

컴포넌트마다 의존하는 스토어의 일부를 고르고, 객체는 shallow로 비교하고, batch로 변경을 묶고, 외부 이벤트를 연결합니다.

이 페이지에서selector 넘기기직접 해 보기여러 필드는 shallow로비교 함수 직접 쓰기batch로 변경 묶기React 밖에서 구독하기외부 이벤트 연결하기

selector 넘기기

컴포넌트가 필요한 것을 고르는 함수를 훅에 넘기세요. 변경이 일어나면 restate가 selector를 실행하고 결과를 이전 결과와 Object.is로 비교합니다. 같다면 컴포넌트는 렌더하지 않습니다.

메모가 바뀌었습니다. ItemCount는 렌더할까요?

아닙니다. selector가 여전히 같은 상품 수를 반환하므로 선택값이 같고, React에 렌더를 요청하지 않습니다.

JavaScript / JSX
const useCart = restate({ items: ['Book'], coupon: '', note: '' });

function ItemCount() {
  // Re-renders only when the number of items changes.
  const count = useCart((cart) => cart.items.length);
  return <p>{count} items</p>;
}

직접 해 보기

필드를 바꾸며 렌더 수를 지켜보세요. shallow를 끄면 매번 새 객체를 반환하는 selector가 어떻게 되는지 볼 수 있습니다.

예제를 준비하는 중…

여러 필드는 shallow로

객체를 만드는 selector는 매번 새 객체를 반환하므로 Object.is는 항상 변화로 봅니다. 두 번째 인자로 shallow를 넘기면 객체의 자기 필드를 한 단계 깊이로 비교합니다.

shallow는 배열, Map, Set의 항목도 한 단계 깊이로 비교합니다.

JavaScript / JSX
import { restate, shallow } from '@kkwaenggwari/restate';

function CartSummary() {
  const { count, coupon } = useCart(
    (cart) => ({ count: cart.items.length, coupon: cart.coupon }),
    shallow,
  );
  return (
    <p>
      {count} items · {coupon || 'no coupon'}
    </p>
  );
}

비교 함수 직접 쓰기

두 번째 인자로 (left, right) => boolean 함수를 넘길 수 있습니다. 목록을 id로 비교하듯 shallow로 부족할 때 쓰세요.

JavaScript / JSX
const ids = useCart(
  (cart) => cart.items.map((item) => item.id),
  (left, right) => left.length === right.length && left.every((id, index) => id === right[index]),
);

batch로 변경 묶기

set은 호출할 때마다 곧바로 구독자에게 알립니다. 한 동작이 여러 스토어를 바꾼다면 batch로 감싸세요. 메모리는 즉시 바뀌고, 구독자는 콜백이 끝난 뒤 한 번 실행됩니다.

JavaScript / JSX
import { batch } from '@kkwaenggwari/restate';

function checkout() {
  batch(() => {
    useCart.set((cart) => ({ ...cart, items: [] }));
    useOrder.set((order) => ({ ...order, status: 'paid' }));
  });
  // Subscribers run once, after both stores changed.
}

React 밖에서 구독하기

subscribeSelector는 선택한 값이 바뀔 때만 호출하며, 같은 비교 함수를 선택적으로 받습니다.

JavaScript / JSX
const stop = useCart.subscribeSelector(
  (cart) => cart.items.length,
  (count, previous) => analytics.track('cart-size', { count, previous }),
);

외부 이벤트 연결하기

restate의 두 번째 인자로 updater를 넘길 수 있습니다. 첫 컴포넌트나 구독자가 듣기 시작할 때 시작하고, 마지막 구독이 끝나면 정리 함수가 실행됩니다. 브라우저 이벤트, 소켓, 센서를 필요할 때만 연결합니다.

start()와 stop()으로 직접 제어할 수도 있습니다.

JavaScript / JSX
import { restate } from '@kkwaenggwari/restate';

// Listens while at least one component or subscriber uses the store.
export const useOnline = restate(true, ({ setState }) => {
  const update = () => setState(navigator.onLine);
  window.addEventListener('online', update);
  window.addEventListener('offline', update);
  update();
  return () => {
    window.removeEventListener('online', update);
    window.removeEventListener('offline', update);
  };
});

문서 검색

모든 가이드의 제목·설명·본문을 검색합니다.