Skip to content

Commit d6cbef0

Browse files
committed
fix: stable reference for cell values
1 parent 0770e0c commit d6cbef0

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ dist-ssr
2323
*.sln
2424
*.sw?
2525
docs/*
26+
*.tgz
-16 KB
Binary file not shown.

src/hooks.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,12 @@ export function useCellValues<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
148148
): [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] // prettier-ignore
149149
export function useCellValues(...cells: NodeRef[]): unknown[] {
150150
const realm = useRealm()
151-
// biome-ignore lint/suspicious/noExplicitAny: I know why we need any here
152-
return useCellValue(realm.combineCells.apply(realm, cells as any))
151+
// biome-ignore lint/correctness/useExhaustiveDependencies: spreading the cells is fine here
152+
const combinedCell = React.useMemo(() => {
153+
// biome-ignore lint/suspicious/noExplicitAny: I know why we need any here
154+
return realm.combineCells.apply(realm, cells as any)
155+
}, [realm, ...cells])
156+
return useCellValue(combinedCell)
153157
}
154158

155159
/**

src/realm.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ interface SignalDefinition<T> {
8787
const nodeDefs$$ = new Map<symbol, CellDefinition<any> | SignalDefinition<any>>()
8888
let currentRealm$$: Realm | undefined = undefined
8989

90+
interface CombinedCellRecord {
91+
sources: symbol[]
92+
cell: NodeRef
93+
}
94+
9095
/**
9196
* The realm is the actual "engine" that orchestrates any cells and signals that it touches. The realm also stores the state and the dependencies of the nodes that are referred through it.
9297
*
@@ -99,6 +104,7 @@ export class Realm {
99104
private readonly distinctNodes = new Map<symbol, Comparator<unknown>>()
100105
private readonly executionMaps = new Map<symbol | symbol[], ExecutionMap>()
101106
private readonly definitionRegistry = new Set<symbol>()
107+
private readonly combinedCells: CombinedCellRecord[] = []
102108

103109
/**
104110
* Creates a new realm.
@@ -968,23 +974,31 @@ export class Realm {
968974
]
969975
): NodeRef<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21]> // prettier-ignore
970976
combineCells(...sources: NodeRef[]): NodeRef {
971-
return tap(
972-
this.cellInstance(
973-
sources.map((source) => this.getValue(source)),
974-
true
975-
),
976-
(sink) => {
977-
this.connect({
978-
map:
979-
(done) =>
980-
(...args) => {
981-
done(args)
982-
},
983-
sink,
984-
sources,
985-
})
986-
}
977+
const existing = this.combinedCells.find((entry) => {
978+
return sources.length === entry.sources.length && sources.every((s, i) => s === entry.sources[i])
979+
})
980+
981+
if (existing) {
982+
return existing.cell
983+
}
984+
985+
const combinedCell = this.cellInstance(
986+
sources.map((source) => this.getValue(source)),
987+
true
987988
)
989+
990+
this.connect({
991+
map:
992+
(done) =>
993+
(...args) => {
994+
done(args)
995+
},
996+
sink: combinedCell,
997+
sources,
998+
})
999+
1000+
this.combinedCells.push({ sources, cell: combinedCell })
1001+
return combinedCell
9881002
}
9891003

9901004
/**

0 commit comments

Comments
 (0)