Skip to content

Commit bd6b012

Browse files
committed
fix: ensure renderOne re-runs update on every call without data
Using a shared null reference caused renderList's identity check to skip the update callback on subsequent renderOne calls. Pass a fresh object each time so the update always runs.
1 parent 2c551a4 commit bd6b012

3 files changed

Lines changed: 53 additions & 2 deletions

File tree

packages/nanotags/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
},
8383
{
8484
"path": ".size-check/render.mjs",
85-
"limit": "410 B"
85+
"limit": "417 B"
8686
},
8787
{
8888
"path": ".size-check/context.mjs",

packages/nanotags/src/render.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,54 @@ describe("render", () => {
220220
expect(container.children[0]).toBe(firstEl);
221221
});
222222

223+
it("re-runs update callback without data on subsequent calls", () => {
224+
const container = createHostWith("");
225+
const tpl = makeTpl("<span></span>");
226+
let callCount = 0;
227+
228+
const update = (el: Element) => {
229+
callCount++;
230+
el.textContent = `call-${callCount}`;
231+
};
232+
233+
render(container, tpl, { update });
234+
expect(callCount).toBe(1);
235+
expect(container.children[0]?.textContent).toBe("call-1");
236+
237+
render(container, tpl, { update });
238+
expect(callCount).toBe(2);
239+
expect(container.children[0]?.textContent).toBe("call-2");
240+
241+
render(container, tpl, { update });
242+
expect(callCount).toBe(3);
243+
expect(container.children[0]?.textContent).toBe("call-3");
244+
});
245+
246+
it("skips update when explicit data has not changed", () => {
247+
const container = createHostWith("");
248+
const tpl = makeTpl("<span></span>");
249+
let callCount = 0;
250+
const data = { name: "Alice" };
251+
252+
render(container, tpl, {
253+
data,
254+
update: (el, d) => {
255+
callCount++;
256+
el.textContent = d.name;
257+
},
258+
});
259+
expect(callCount).toBe(1);
260+
261+
render(container, tpl, {
262+
data,
263+
update: (el, d) => {
264+
callCount++;
265+
el.textContent = d.name;
266+
},
267+
});
268+
expect(callCount).toBe(1);
269+
});
270+
223271
it("switches between different templates", () => {
224272
const container = createHostWith("");
225273
const loadingTpl = makeTpl('<div class="loading">Loading...</div>');

packages/nanotags/src/render.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,11 @@ export function render<T, E extends Element = Element>(
8787
template: HTMLTemplateElement,
8888
options?: RenderOptions<T, E>,
8989
): void {
90+
// When no explicit data is provided, use a fresh object each call
91+
// so renderList's identity check always passes and update always runs
92+
const data = [options !== undefined && "data" in options ? options.data : {}] as T[];
9093
renderList(container, template, {
91-
data: [options?.data ?? (null as T)],
94+
data,
9295
key: () => {
9396
let id = tplIds.get(template);
9497
if (id === undefined) {

0 commit comments

Comments
 (0)