$derived.by accepts a function for calculations that need more than one expression. Keep the calculation free of side effects.
<script>
let todos = $state([
{ task: 'Walk dog', completed: false },
]);
let remaining = $derived.by(() => {
let count = 0;
for (const todo of todos) {
if (!todo.completed) count++;
}
return count;
});
</script>
{#each todos as todo}
<label>
<input type="checkbox" bind:checked={todo.completed}>
{todo.task}
</label>
{/each}
<p>{remaining} todos left</p>