restate / v1.0.0
Abonneer je alleen op wat je nodig hebt
Kies van welk deel van een store elk component afhangt, vergelijk objecten met shallow, groepeer wijzigingen met batch en koppel externe events.
Op deze pagina
Geef een selector doorProbeer hetSelecteer meerdere velden met shallowSchrijf je eigen vergelijkingGroepeer wijzigingen met batchAbonneren buiten ReactKoppel externe eventsGeef een selector door
Roep de hook aan met een functie die kiest wat het component nodig heeft. Na elke wijziging voert restate de selector uit en vergelijkt het resultaat met het vorige via Object.is. Als ze gelijk zijn, rendert het component niet.
De kaart verandert. Rendert ItemCount?
Nee. De selector geeft nog steeds hetzelfde aantal artikelen terug, dus de selectie is gelijk en React wordt niet gevraagd om te renderen.
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>;
}Probeer het
Verander de velden en kijk naar de rendertellers. Zet shallow uit om een selector te zien die elke keer een nieuw object teruggeeft.
Voorbeeld voorbereiden…
Selecteer meerdere velden met shallow
Een selector die een object bouwt, geeft elke keer een nieuw object terug, dus Object.is ziet altijd een verandering. Geef shallow mee als tweede argument: het vergelijkt de eigen velden van het object één niveau diep.
shallow vergelijkt ook de items van arrays, Map en Set één niveau diep.
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>
);
}Schrijf je eigen vergelijking
Elke functie (left, right) => boolean werkt als tweede argument. Gebruik er een als shallow niet genoeg is, bijvoorbeeld om een lijst op id te vergelijken.
const ids = useCart(
(cart) => cart.items.map((item) => item.id),
(left, right) => left.length === right.length && left.every((id, index) => id === right[index]),
);Groepeer wijzigingen met batch
Elke set meldt het abonnees direct. Als één actie meerdere stores verandert, wikkel haar dan in batch: het geheugen wordt meteen bijgewerkt en abonnees draaien één keer na de 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.
}Abonneren buiten React
subscribeSelector roept je alleen aan als de geselecteerde waarde verandert, met dezelfde optionele vergelijkingsfunctie.
const stop = useCart.subscribeSelector(
(cart) => cart.items.length,
(count, previous) => analytics.track('cart-size', { count, previous }),
);Koppel externe events
Het tweede argument van restate kan een updater zijn. Die start zodra het eerste component of de eerste abonnee begint te luisteren, en de opruimfunctie draait als de laatste stopt, zodat browserevents, sockets of sensoren alleen gekoppeld blijven zolang dat nodig is.
Gebruik start() en stop() om hem handmatig te bedienen.
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);
};
});