mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Signed-off-by: Matt Toohey <contact@matttoohey.com> Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
import * as React from "react";
|
|
|
|
/**
|
|
* Returns `next` but preserves the previous reference whenever the two Maps
|
|
* have identical entries (same size, same key→value pairs). Lets a value that
|
|
* is recomputed into a fresh Map on an unrelated invalidation (e.g. a version
|
|
* bump) keep a stable identity so downstream `React.memo` boundaries can bail.
|
|
*/
|
|
export function useStableMap<K, V>(next: Map<K, V>): Map<K, V> {
|
|
const ref = React.useRef(next);
|
|
const prev = ref.current;
|
|
if (prev !== next && mapsEqual(prev, next)) {
|
|
return prev;
|
|
}
|
|
ref.current = next;
|
|
return next;
|
|
}
|
|
|
|
function mapsEqual<K, V>(a: Map<K, V>, b: Map<K, V>): boolean {
|
|
if (a.size !== b.size) return false;
|
|
for (const [key, value] of a) {
|
|
if (!b.has(key) || !Object.is(b.get(key), value)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns `next` but preserves the previous reference when the two arrays are
|
|
* shallow-equal (same length, `Object.is` on each element). Same purpose as
|
|
* `useStableMap` for array-valued derived state. Preserves the caller's exact
|
|
* array type (mutable or readonly).
|
|
*/
|
|
export function useStableArrayShallow<T extends readonly unknown[]>(
|
|
next: T,
|
|
): T {
|
|
const ref = React.useRef(next);
|
|
const prev = ref.current;
|
|
if (prev !== next && arraysShallowEqual(prev, next)) {
|
|
return prev;
|
|
}
|
|
ref.current = next;
|
|
return next;
|
|
}
|
|
|
|
function arraysShallowEqual(
|
|
a: readonly unknown[],
|
|
b: readonly unknown[],
|
|
): boolean {
|
|
if (a.length !== b.length) return false;
|
|
for (let i = 0; i < a.length; i += 1) {
|
|
if (!Object.is(a[i], b[i])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns `next` but preserves the previous reference when the two Sets have
|
|
* identical membership. Same purpose as `useStableMap` for Set-valued derived
|
|
* state (e.g. pubkey sets rebuilt whenever a polling query re-materialises
|
|
* its data without changing which pubkeys are in it).
|
|
*/
|
|
export function useStableSet<T>(next: ReadonlySet<T>): ReadonlySet<T> {
|
|
const ref = React.useRef(next);
|
|
const prev = ref.current;
|
|
if (prev !== next && setsEqual(prev, next)) {
|
|
return prev;
|
|
}
|
|
ref.current = next;
|
|
return next;
|
|
}
|
|
|
|
function setsEqual<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): boolean {
|
|
if (a.size !== b.size) return false;
|
|
for (const value of a) {
|
|
if (!b.has(value)) return false;
|
|
}
|
|
return true;
|
|
}
|