[*] Support request
[*] Bug report ??
In this stackblitz I have a simple user entityStore with activeState and a filter property:
export interface UserState extends EntityState<User>, ActiveState {
filter: string;
}
let initialState: UserState = {
active: null,
filter: '',
}
in AppComponent I get users from api and display it. And I filter user's username property via a FormControl
in Component2 I display a json of the selected user
In Component2, when I select activeId I got notified 2 times, first with the correct value, then by the previous value (you can see the log in the console)
this.userQuery.selectActiveId().subscribe( id => {
console.log(id) // logged twice and changed to previous value
this.user = this.userQuery.getEntity(id);
})
I couldn't determine the cause so if you please help me figure it out.
select property fire only once
```ts
// AppComponent
this.userService.get().subscribe();
this.userQuery.selectUsers$.subscribe(users => {
const active = users.length ? users[0].id : null;
this.userService.updateActiveId(active);
});
// Comp B
this.userQuery.selectActiveId().subscribe( id => {
console.log(id);
})
```
Ok, so here's what's happening:
App starts:
selectUsers$ emits synchronously, and updates active to null.selectActiveId emits synchronously with null.So far, so good.
userService.get() returns:
store.set() which changes active to null, and updates the users.selectUsers$ emits synchronously with the users and update active to the first user id.selectActiveId emits synchronously and recivies the new active id.But now we have a problem. The selectActiveId subscriber still needs to get the emission fired as a result of the store update, which changed the active to null. That's why you see: null, id, null
You have two options:
delay(0) to selectUsers$active update to the service: return this.http
.get<User[]>("https://jsonplaceholder.typicode.com/users")
.pipe(
tap(users => {
applyTransaction(() => {
this.userStore.set(users);
let found: boolean = !!users.find(
o => o.id == this.userQuery.getActiveId()
);
let id: number = users.length
? found
? this.userQuery.getActiveId()
: users[0].id
: null;
this.updateActiveId(id);
});
})
);
I have added in the latest version the option to pass the active id to set:
this.userStore.set(users, { activeId: users[0].id });
Thanks. This issue was hanging for a while. It recurred several time with in my project with different forms. It drove me crazy for not being able to determine the cause. I was just about to switch temporarily back to ngrx till this issue get fixed.
The delay(0) solution is good. It defers the execution from synchronous to asynchronous and problem solved.
I think I'll stick to delay(0) solution as it fix another issue with
userStore.remove(id);
like you did in this fix:
I have added in the latest version the option to pass the active id to
set:this.userStore.set(users, { activeId: users[0].id });
I think you should add similar fix to store.remove(id) to update the next active id
this.userStore.remove(id, { activeId: nextId });
Let me give you a tip. It's not nice to say to an author of open-source library things like " I was just about to switch temporarily back to ngrx till this issue get fixed."
You're welcome to submit a PR and add the same functionality to the remove method.
I don't think there a competition between state management libraries here.
But let me tell you, if you take it this way, and if it calms you down: with continuous support, Akita will outrun other libraries for sure, and it should be the official @angular/state library.
Most helpful comment
Let me give you a tip. It's not nice to say to an author of open-source library things like " I was just about to switch temporarily back to ngrx till this issue get fixed."
You're welcome to submit a PR and add the same functionality to the remove method.