Overview

memoHtml(templateFn, deps?) calls templateFn only when one or more deps changed since the last render (strict === per index, same as lit-html guard). Factory first so it reads naturally inside html`…`.

Default deps are [] — evaluate once. A change in deps array length always counts as a change. The deps array is snapshotted.

memoTemplate is a deprecated alias.

memoHtml vs memo vs guard

API
Layer
Notes
memo(fn) State Derived reactive value — see /docs/state/memo.
memoHtml(fn, deps) Template Skip subtree factory when deps unchanged.
guard(deps, fn) lit-html Same idea; deps first. memoHtml flips the argument order.

Skip rebuild on unrelated parent ticks

Parent re-renders on ticks, but the card factory only runs when name() changes.

import { html, atom, memoHtml, renderApp } from 'mates';

const App = () => {
const name = atom('Ada');
const ticks = atom(0);

return () => html`
<div class="m-col m-gap">
<p class="label">Parent ticks: ${ticks()} (does not rebuild the memoized card)</p>
<div class="m-flex m-items-center m-justify-center m-gap-sm">
<button @click=${() => ticks.set((n) => n + 1)}>Tick parent</button>
<button class="btn-primary" @click=${() => name.set((n) => n === 'Ada' ? 'Grace' : 'Ada')}>
Change name
</button>
</div>
${memoHtml(
() => html`
<div class="card card-body">
<strong>${name()}</strong>
<p class="label m-t-5">memoHtml deps: [name]</p>
</div>
`,
[name()],
)}
</div>
`;
};
renderApp(App, document.getElementById('app'));

Per-row memoization

Each button’s factory depends on id, label, and selected equality — other rows stay cached.

import { html, atom, memoHtml, renderApp } from 'mates';

const App = () => {
const selected = atom(1);
const items = [
{ id: 1, label: 'Alpha' },
{ id: 2, label: 'Beta' },
{ id: 3, label: 'Gamma' },
];

return () => html`
<div class="m-col m-gap">
${items.map((item) =>
memoHtml(
() => html`
<button
class=${selected() === item.id ? 'btn-primary' : 'btn-ghost'}
@click=${() => selected.set(item.id)}
>${item.label}</button>
`,
[item.id, item.label, selected() === item.id],
),
)}
</div>
`;
};
renderApp(App, document.getElementById('app'));