I have a component like user-personal-details.component.ts
. Which stays in sync with user
stored in Store
@Select() user$: Observable<IUser>;
user:IUser;
ngOnInit() {
this.user$.subscribe((user:IUser)=>{
this.user = user;
this.form.form.patchValue(user);//LINE A: fill the form using user data
};
}
This component has a form to fill details about the user
. There is no save button, everytime user type of any of these component, I detect changes via
this.form.valueChanges.debounce(2000).subscribe((formData)=>{
this.store.dispatch(new UpdateUser(formData));//Line B
})
and dispatch an Action
named UpdateUser
to store changes in Store
.
Problem:
Problem is when user will type something, it will dispatch action to change User in store (Line B). Since component is subscribed to user
in store, Line A will be called again. Which in turn, patch the form hence calling Line B. Thus making it a cycle.
One way to avoid this is mutate the state when form changes because that will not fire an action and hence line B will not be called. But I think thats not recommended in Redux.
Can someone suggest a more elegant way to deal with this problem?
Note: I am using NGXS for this but I guess it shouldn't make a difference.
Edit: Since the question was downvoted, I made a big edit to this question to make the problem minimal.
I believe that you should populate the form with user from store only once at the beginning when form is loaded. Any later change of the user form shouldn't change the form anymore. The form will be source of truth in that case. It will not sync data from the store anymore but to the store.
You can use take
operator for that:
this.user$.pipe(take(1)).subscribe((user:IUser)=>{
this.user = user;
this.form.form.patchValue(user);//LINE A: fill the form using user data
};
BTW also consider using form plugin for NGXS