restate / v1.0.0
Prenumerera bara på det du behöver
Välj vilken del av en store varje komponent beror på, jämför objekt med shallow, gruppera ändringar med batch och koppla in externa händelser.
På den här sidan
Skicka en selectorProvaVälj flera fält med shallowSkriv din egen jämförelseGruppera ändringar med batchPrenumerera utanför ReactKoppla in externa händelserSkicka en selector
Anropa hooken med en funktion som väljer det komponenten behöver. Efter varje ändring kör restate din selector och jämför resultatet med det föregående med Object.is. Om de är lika renderas komponenten inte.
Kortet ändras. Renderas ItemCount?
Nej. Dess selector returnerar fortfarande samma antal artiklar, så urvalet är lika och React ombeds inte rendera den.
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>;
}Prova
Ändra fälten och titta på renderingsräknarna. Stäng av shallow för att se en selector som returnerar ett nytt objekt varje gång.
Förbereder exemplet…
Välj flera fält med shallow
En selector som bygger ett objekt returnerar ett nytt varje gång, så Object.is ser alltid en förändring. Skicka shallow som andra argument: den jämför objektets egna fält en nivå djupt.
shallow jämför också element i arrayer, Map och Set en nivå djupt.
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>
);
}Skriv din egen jämförelse
Vilken funktion (left, right) => boolean som helst fungerar som andra argument. Använd en när shallow inte räcker, till exempel för att jämföra en lista på id.
const ids = useCart(
(cart) => cart.items.map((item) => item.id),
(left, right) => left.length === right.length && left.every((id, index) => id === right[index]),
);Gruppera ändringar med batch
Varje set aviserar prenumeranter direkt. När en handling ändrar flera stores, slå in den i batch: minnet uppdateras direkt och prenumeranterna körs en gång efter callbacken.
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.
}Prenumerera utanför React
subscribeSelector anropar dig bara när det valda värdet ändras, med samma valfria jämförelsefunktion.
const stop = useCart.subscribeSelector(
(cart) => cart.items.length,
(count, previous) => analytics.track('cart-size', { count, previous }),
);Koppla in externa händelser
Det andra argumentet till restate kan vara en updater. Den startar när den första komponenten eller prenumeranten börjar lyssna, och dess städning körs när den sista slutar, så webbläsarhändelser, sockets eller sensorer är kopplade bara så länge de behövs.
Använd start() och stop() för att styra den manuellt.
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);
};
});