restate / v1.0.0
נרשמים רק למה שצריך
בחרו מאיזה חלק של המאגר כל רכיב תלוי, השוו אובייקטים עם shallow, קבצו שינויים עם batch וחברו אירועים חיצוניים.
בעמוד הזה
העבירו selectorנסו את זהבחירת כמה שדות עם shallowפונקציית השוואה משלכםקיבוץ שינויים עם batchהרשמה מחוץ ל־Reactחיבור אירועים חיצונייםהעבירו selector
קראו ל־hook עם פונקציה שבוחרת את מה שהרכיב צריך. אחרי כל שינוי restate מריץ את ה־selector ומשווה את התוצאה לקודמת עם Object.is. אם הן שוות, הרכיב לא מתרנדר.
הכרטיס משתנה. האם ItemCount מתרנדר?
לא. ה־selector שלו עדיין מחזיר את אותו מספר פריטים, כך שהבחירה שווה ו־React לא מתבקש לרנדר אותו.
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.
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.
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: הזיכרון מתעדכן מיד, והמנויים רצים פעם אחת אחרי ה־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.
}הרשמה מחוץ ל־React
subscribeSelector קורא לכם רק כשהערך הנבחר משתנה, עם אותה פונקציית השוואה אופציונלית.
const stop = useCart.subscribeSelector(
(cart) => cart.items.length,
(count, previous) => analytics.track('cart-size', { count, previous }),
);חיבור אירועים חיצוניים
הארגומנט השני של restate יכול להיות updater. הוא מתחיל כשהרכיב או המנוי הראשון מתחיל להאזין, והניקוי שלו רץ כשהאחרון מפסיק, כך שאירועי דפדפן, sockets או חיישנים מחוברים רק כל עוד צריך אותם.
השתמשו ב־start() וב־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);
};
});