restate / v1.0.0
Odebírejte jen to, co potřebujete
Zvolte, na které části store každá komponenta závisí, porovnávejte objekty přes shallow, seskupujte změny přes batch a připojujte vnější události.
Na této stránce
Předejte selectorVyzkoušejteVýběr více polí přes shallowVlastní porovnáníSeskupení změn přes batchOdběr mimo ReactPřipojení vnějších událostíPředejte selector
Zavolejte hook s funkcí, která vybere, co komponenta potřebuje. Po každé změně restate spustí selector a porovná výsledek s předchozím přes Object.is. Pokud jsou stejné, komponenta se nepřekreslí.
Kartička se změní. Překreslí se ItemCount?
Ne. Jeho selector pořád vrací stejný počet položek, takže výběr je stejný a React nemusí nic překreslovat.
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>;
}Vyzkoušejte
Měňte pole a sledujte počítadla renderů. Vypněte shallow a uvidíte selector, který pokaždé vrací nový objekt.
Příprava příkladu…
Výběr více polí přes shallow
Když selector skládá objekt, vrací pokaždé nový, takže Object.is vždy vidí změnu. Předejte shallow jako druhý argument: porovná vlastní pole objektu do hloubky jedné úrovně.
shallow porovnává do jedné úrovně i prvky polí, Map a Set.
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>
);
}Vlastní porovnání
Jako druhý argument poslouží jakákoli funkce (left, right) => boolean. Použijte ji, když shallow nestačí, například pro porovnání seznamu podle id.
const ids = useCart(
(cart) => cart.items.map((item) => item.id),
(left, right) => left.length === right.length && left.every((id, index) => id === right[index]),
);Seskupení změn přes batch
Každé set hned upozorní odběratele. Když jedna akce mění více store, obalte ji do batch: paměť se aktualizuje hned a odběratelé se spustí jednou po callbacku.
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.
}Odběr mimo React
subscribeSelector vás zavolá, jen když se vybraná hodnota změní, se stejnou volitelnou porovnávací funkcí.
const stop = useCart.subscribeSelector(
(cart) => cart.items.length,
(count, previous) => analytics.track('cart-size', { count, previous }),
);Připojení vnějších událostí
Druhým argumentem restate může být updater. Spustí se, když začne poslouchat první komponenta nebo odběratel, a jeho úklid proběhne, když přestane poslední, takže události prohlížeče, sockety nebo senzory jsou připojené jen po dobu, kdy jsou potřeba.
Pro ruční ovládání použijte start() a stop().
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);
};
});