restate / v1.0.0
Iscriviti solo a ciò che ti serve
Scegli da quale parte di uno store dipende ogni componente, confronta oggetti con shallow, raggruppa le modifiche con batch e collega eventi esterni.
In questa pagina
Passa un selectorProvaloSeleziona più campi con shallowScrivi il tuo confrontoRaggruppa le modifiche con batchIscriviti fuori da ReactCollega eventi esterniPassa un selector
Chiama l’hook con una funzione che sceglie ciò che serve al componente. Dopo ogni modifica restate esegue il selector e confronta il risultato con il precedente usando Object.is. Se sono uguali, il componente non si renderizza.
Il biglietto cambia. ItemCount si renderizza?
No. Il suo selector restituisce ancora lo stesso numero di articoli, quindi la selezione è uguale e a React non viene chiesto di renderizzarlo.
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>;
}Provalo
Cambia i campi e guarda i contatori dei render. Disattiva shallow per vedere un selector che restituisce ogni volta un oggetto nuovo.
Preparazione dell’esempio…
Seleziona più campi con shallow
Un selector che costruisce un oggetto ne restituisce ogni volta uno nuovo, quindi Object.is vede sempre un cambiamento. Passa shallow come secondo argomento: confronta i campi propri dell’oggetto a un livello di profondità.
shallow confronta a un livello anche gli elementi di array, Map e 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>
);
}Scrivi il tuo confronto
Qualsiasi funzione (left, right) => boolean va bene come secondo argomento. Usala quando shallow non basta, per esempio per confrontare una lista per id.
const ids = useCart(
(cart) => cart.items.map((item) => item.id),
(left, right) => left.length === right.length && left.every((id, index) => id === right[index]),
);Raggruppa le modifiche con batch
Ogni set notifica subito gli iscritti. Quando un’azione cambia più store, avvolgila in batch: la memoria si aggiorna subito e gli iscritti vengono eseguiti una volta dopo il callback.
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.
}Iscriviti fuori da React
subscribeSelector ti chiama solo quando cambia il valore selezionato, con la stessa funzione di confronto opzionale.
const stop = useCart.subscribeSelector(
(cart) => cart.items.length,
(count, previous) => analytics.track('cart-size', { count, previous }),
);Collega eventi esterni
Il secondo argomento di restate può essere un updater. Parte quando il primo componente o iscritto inizia ad ascoltare, e la sua pulizia viene eseguita quando l’ultimo smette, così eventi del browser, socket o sensori restano collegati solo finché servono.
Usa start() e stop() per controllarlo a mano.
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);
};
});