Open
Description
Describe the bug
Something seems to have changed recently in the way $derived works.
This test below used to update the lookup on addition of children attribute.
it.only('should handle a nested array', () => {
const items = $state([{ text: 'A' }, { text: 'B' }, { text: 'C' }])
const lookup = $derived(deriveLookupWithProxy(items))
const result = () => lookup
expect(Array.from(result().keys())).toEqual(['0', '1', '2'])
const addChildren = () => {
items[0].children = [{ text: 'A1' }, { text: 'A2' }]
}
addChildren()
// flushSync()
expect(Array.from(result().keys())).toEqual(['0', '0-0', '0-1', '1', '2'])
})
I still see that the function is called on the change, but it does not seem to update the values. This used to work recently.
Reproduction
import { describe, it, expect } from 'vitest'
import { isNil, has } from 'ramda'
// import { flushSync } from 'svelte'
const defaultFields = { children: 'children' }
class Proxy {
constructor(value, fields) {
this.fields = fields
this.value = value
}
get(fieldName, defaultValue) {
return this.has(fieldName) ? this.value[this.fields[fieldName]] : defaultValue
}
has(fieldName) {
const mappedField = this.fields[fieldName]
return !isNil(mappedField) && has(mappedField, this.value)
}
get hasChildren() {
return this.has('children') && Array.isArray(this.value[this.fields.children])
}
}
export function deriveLookupWithProxy(items, fields = defaultFields, path = []) {
const lookup = new Map()
console.log($state.snapshot(items))
items.forEach((item, index) => {
const itemPath = [...path, index]
const key = itemPath.join('-')
const proxy = new Proxy(item, fields)
lookup.set(key, proxy)
if (proxy.hasChildren) {
const childLookup = deriveLookupWithProxy(proxy.get('children'), fields, itemPath)
for (const [childKey, childValue] of childLookup.entries()) {
lookup.set(childKey, childValue)
}
}
})
return lookup
}
describe('deriveLookupWithProxy', () => {
it.only('should handle a nested array', () => {
const items = $state([{ text: 'A' }, { text: 'B' }, { text: 'C' }])
const lookup = $derived(deriveLookupWithProxy(items))
const result = () => lookup
expect(Array.from(result().keys())).toEqual(['0', '1', '2'])
const addChildren = () => {
items[0].children = [{ text: 'A1' }, { text: 'A2' }]
}
addChildren()
// flushSync()
expect(Array.from(result().keys())).toEqual(['0', '0-0', '0-1', '1', '2'])
})
})
Logs
System Info
System:
OS: macOS 15.4.1
CPU: (16) arm64 Apple M4 Max
Memory: 640.27 MB / 48.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 23.4.0 - ~/.nvm/versions/node/v23.4.0/bin/node
npm: 10.9.2 - ~/.nvm/versions/node/v23.4.0/bin/npm
pnpm: 10.7.0 - ~/Library/pnpm/pnpm
bun: 1.2.12 - /opt/homebrew/bin/bun
Browsers:
Chrome: 136.0.7103.93
Safari: 18.4
Severity
blocking an upgrade
Metadata
Metadata
Assignees
Labels
No labels