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. Використовуйте її, коли shallow замало, наприклад щоб порівнювати список за id.

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);
  };
});

Пошук у документації

Пошук у заголовках, описах і тексті всіх посібників.