Skip to content

Commit 366619b

Browse files
Generate a cid for repeat elements if no id (#59)
IDs enable efficient re-rendering of dynamic lists. However, if a model does not provide an ID, we should just generate one for the purpose of making the logic work. Those items will not get efficient re-rendering (they will be destroyed and re-created), but it will still work. This is the same tradeoff React makes.
1 parent 75e5412 commit 366619b

File tree

1 file changed

+19
-5
lines changed
  • typescript/packages/common-ui/src/hyperscript

1 file changed

+19
-5
lines changed

typescript/packages/common-ui/src/hyperscript/render.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ const renderText = (element: Element, value: any): Cancel =>
209209
/** Symbol for list item key */
210210
const __id__ = Symbol("list item key");
211211

212+
let _cid = 0;
213+
const cid = () => `cid${_cid++}`
214+
212215
/**
213216
* An element with an id symbol used for efficient rendering of dynamic lists.
214217
*/
@@ -225,8 +228,19 @@ export const renderDynamicChildren = (
225228
return;
226229
}
227230

228-
// Build a map of states by id for quick lookup
229-
const statesById = new Map(gmap(states, (state) => [state.id, state]));
231+
// Build a map of states by id for quick lookup.
232+
// If model doesn't have an ID, generate one. Generated ID will mean the
233+
// item will not be efficiently re-rendered by identity, but it will
234+
// still work.
235+
const statesById = new Map(
236+
gmap(
237+
states,
238+
(state) => [
239+
state.id ?? cid(),
240+
state
241+
]
242+
)
243+
);
230244

231245
// Build an index of children and a list of children to remove.
232246
// Note that we must build a list of children to remove, since
@@ -235,11 +249,11 @@ export const renderDynamicChildren = (
235249
const removes: Array<Element> = [];
236250

237251
for (const child of parent.children) {
238-
const keyedChild = child as IdentifiedChild;
239-
const childId = keyedChild[__id__];
252+
const identifiedChild = child as IdentifiedChild;
253+
const childId = identifiedChild[__id__];
240254
children.set(childId, child);
241255
if (!statesById.has(childId)) {
242-
removes.push(child);
256+
removes.push(identifiedChild);
243257
}
244258
}
245259

0 commit comments

Comments
 (0)