Computed value is not recomputed after dependencies change #219
Description
🐛 Bug report
I have a problem with not updating computed values. I am using a demo API to download and insert users into a collection. I want to use a computed value to get a user from this collection based on a user id, which is defined in a state. The first compute works with the default user id, but after updating the user id the value is not recomputed. I took a look at the deps prop and found all the necessary observers with the correct values, though the value of the computed user was incorrect.
The first compute only works if I define the computed value after inserting the users into the collection, otherwise this computed value is stuck on undefined.
🤖 Current Behavior
const data: any[] = await fetch('https://jsonplaceholder.typicode.com/users').then(res => res.json());
const userCollection = createCollection();
const selectedUserId = createState(1);
selectedUserId.watch(() => console.log("---- new selected user id!"));
for (const item of data) {
userCollection.collect(item);
}
const selectedUser = createComputed(() => {
return userCollection.getItemValue(selectedUserId.value);
});
console.log("auto:", selectedUser.value);
selectedUserId.set(2);
console.log("manual:", userCollection.getItemValue(selectedUserId.value));
console.log("auto:", selectedUser.value);
console.log(selectedUser.deps);
output:
auto: {
id: 1,
name: 'Leanne Graham',
username: 'Bret',
email: 'Sincere@april.biz',
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: { lat: '-37.3159', lng: '81.1496' }
},
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
company: {
name: 'Romaguera-Crona',
catchPhrase: 'Multi-layered client-server neural-net',
bs: 'harness real-time e-markets'
}
}
---- new selected user id!
manual: {
id: 2,
name: 'Ervin Howell',
username: 'Antonette',
email: 'Shanna@melissa.tv',
address: {
street: 'Victor Plains',
suite: 'Suite 879',
city: 'Wisokyburgh',
zipcode: '90566-7771',
geo: { lat: '-43.9509', lng: '-34.4618' }
},
phone: '010-692-6593 x09125',
website: 'anastasia.net',
company: {
name: 'Deckow-Crist',
catchPhrase: 'Proactive didactic contingency',
bs: 'synergize scalable supply-chains'
}
}
auto: {
id: 1,
name: 'Leanne Graham',
username: 'Bret',
email: 'Sincere@april.biz',
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: { lat: '-37.3159', lng: '81.1496' }
},
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
company: {
name: 'Romaguera-Crona',
catchPhrase: 'Multi-layered client-server neural-net',
bs: 'harness real-time e-markets'
}
}
Set(2) {
StateObserver {
agileInstance: [Function (anonymous)],
key: undefined,
dependents: Set(1) { [StateObserver] },
subscribedTo: Set(0) {},
value: 2,
previousValue: 1,
state: [Function (anonymous)],
nextStateValue: 2
},
StateObserver {
agileInstance: [Function (anonymous)],
key: 2,
dependents: Set(1) { [StateObserver] },
subscribedTo: Set(0) {},
value: {
id: 2,
name: 'Ervin Howell',
username: 'Antonette',
email: 'Shanna@melissa.tv',
address: [Object],
phone: '010-692-6593 x09125',
website: 'anastasia.net',
company: [Object]
},
previousValue: null,
state: [Function (anonymous)],
nextStateValue: {
id: 2,
name: 'Ervin Howell',
username: 'Antonette',
email: 'Shanna@melissa.tv',
address: [Object],
phone: '010-692-6593 x09125',
website: 'anastasia.net',
company: [Object]
}
}
}
🎯 Expected behavior
I would expect this to work, as defined in the docs.
const MY_COMPUTED = createComputed(() => {
const user = USERS.getItemValue(CURRENT_USER_ID.value);
return `My name is '${user?.name} and I am ${user?.age} years old.`;
});
MY_COMPUTED.value; // Returns "My name is 'hans' and I am 10 years old."
USERS.update(CURRENT_USER_ID.value, {name: 'jeff'})
MY_COMPUTED.value; // Returns "My name is 'jeff' and I am 10 years old."
📄 Reproducible example
I created a simple main.ts file and ran it with ts-node.
import { createState, createCollection, createComputed } from "@agile-ts/core";
import fetch from 'cross-fetch';
async function init() {
const data: any[] = await fetch('https://jsonplaceholder.typicode.com/users').then(res => res.json());
const userCollection = createCollection();
const selectedUserId = createState(1);
selectedUserId.watch(() => console.log("---- new selected user id!"));
for (const item of data) {
userCollection.collect(item);
}
const selectedUser = createComputed(() => {
return userCollection.getItemValue(selectedUserId.value);
});
console.log("auto:", selectedUser.value);
selectedUserId.set(2);
console.log("manual:", userCollection.getItemValue(selectedUserId.value));
console.log("auto:", selectedUser.value);
console.log(selectedUser.deps);
}
init();
💡 Suggested solution(s)
➕ Additional notes
💻 Your environment
Software | Version(s) |
---|---|
TypeScript | v4.5.4 |
npm/Yarn | v8.3.2 |
NodeJs | v14.18.2 |
@agile-ts/core | v0.2.8 |
@agile-ts/react | N/A |
@agile-ts/api | N/A |
@agile-ts/multieditor | N/A |
ts-node | v10.4.0 |