How to avoid loops in NGRX or NGXS
How to avoid loops in NGRX or NGXS
I have a component like user-personal-details.component.ts
. Which stays in sync with user
stored in Store
user-personal-details.component.ts
user
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
user
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
.
Action
UpdateUser
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.
user
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.
1 Answer
1
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:
take
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
@dasfdsa why you cant do that? So there is another button which fills data to the form and since then form is again source of truth. Its the same situation.
– Martin Nuc
Sep 10 '18 at 19:55
Thanks again. 1. reset button fetches the fresh data from server and stores it into the store. 2. Since component has subscribed to this.user$ it will again patch the form. 3. Since the form has been patched this.form.valueChanges will run its callback and dispatches the action to change the store. 4. this callbac.user$ subscription callback will run....and the cycle continues. Sorry for the late response.
– dasfdsa
Sep 14 '18 at 15:30
If I do this.user$.pipe(take(1)). My form will not be patched like its happening in step 2.
– dasfdsa
Sep 14 '18 at 15:31
@dasfdsa when clicking reset it should reload the user and patch the form itself with reloaded data. You could event have a method
refreshFrom
which reload store from server and patches the form. But dont let the component listening for data all the time imho.– Martin Nuc
Sep 14 '18 at 15:35
refreshFrom
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Thanks for your response. I can't do that. I have a reset button which when clicked, discard all the user changes, and fills the forms with fresh server verison of the form.
– dasfdsa
Sep 10 '18 at 15:47