-
Notifications
You must be signed in to change notification settings - Fork 405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(store): implements ngxsOnChanges #1389
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting!
Could you describe the API and its usages a bit in the description... this could become docs later ;-)
@markwhitfeld This API unifies the life cycle, thereby making our states universal and similar to Angular components. https://angular.io/guide/lifecycle-hooks Also there are many reasons to add this functionality, so it is necessary in the following use cases:
Before @State({ })
class MyState {
} @Component({ })
class MyComponent {
constructor(store: Store) {
store.select(MyState).subscribe((newState) => {
console.log('state is changed', newState);
})
}
} One of the problems is, if we do not use the logging plugin (the official example does not use it), then we do not know what the previous state was before our state changed. It's great to have such an opportunity out of the box. After @State({ })
class MyState {
ngxsOnChanges({ previousValue, currentValue }: NgxsSimpleChange) {
console.log('state is changed', previousValue, currentValue);
}
} Very comfortably! Note: Why https://angular.io/api/core/SimpleChange
In my work when using state, I needed to save state on the server every time the client changed it. Before @State({ })
class MyState {
} @Component({ })
class MyComponent {
constructor(store: Store, api: ApiService) {
store.select(MyState).subscribe(async (newState) => {
await api.saveToRedis(newState);
})
}
} After @State({ })
class MyState {
constructor(api: ApiService) {}
async ngxsOnChanges({ currentValue: newState }: NgxsSimpleChange) {
await api.saveToRedis(newState);
}
}
@State({ })
class MyState {
ngxsOnChanges({ previousValue, currentValue }: NgxsSimpleChange) {
console.log('prev state', previousValue); // you can add color
console.log('next state', currentValue); // you can add color
}
} Or @State({ })
class MyState {
constructor(myLogger: MyLoggerService) {}
ngxsOnChanges(change: NgxsSimpleChange) {
myLogger.prettyDiffChanges(change);
}
} This will allow users to independently control logging without complaining about bugs of the logging plugin (#561, #276, #213). Why One of the main reasons is that users should not manipulate state in this hook! Therefore, we should not motivate them to do this! If that were so @State({ })
class MyState {
ngxsOnChanges(_: NgxsSimpleChange, ctx: StateContext<any>) {
ctx.patchState({ onChange: true }); // Error: Maximum call stack size exceeded error
}
} Because the hook is called before setting the state, but if we allow the user to do in this method, then this will lead to various kinds of errors. However, now users can make such mistakes. @State({
name: 'counter',
defaults: 0
})
class MyState {
constructor(private store: Store) {}
ngxsOnChanges() {
this.store.dispatch({ type: 'increment' }); // Error: Maximum call stack size exceeded error
}
@Action({ type: 'increment' })
increment({ setState }: StateContext<number>) {
setState((state: number) => ++state);
}
} In the future I will add verification so that users do not make such errors. It will be very similar to this ExpressionChangedAfterItHasBeenCheckedError in Angular (problem with recursive change detection) I will add a check, which in developer mode will check and throw an exception when users try to change the state directly in this hook ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nicely done!
I really like the potential for this feature. It can simplify a great deal.
It also has a great harmony with the existing Angular lifecycle.
@arturovt What do you think?
Once @arturovt is happy then we can merge and add to the 3.6 release. |
cc @joaqcid I would like to hear your thoughts here too... |
i like this hook! i think it can be very handy for the scenarios described |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better with those changes.
Just some comments below to discuss.
@arturovt Would you like to review? |
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: #749
What is the new behavior?
The method receives a NgxsSimpleChanges object of current and previous property values. This is convenient if we want to dispatch any additional actions when any fields have changed. Called whenever state change.
The main motivation is that this is a convenient hook in order to save states on the server, if we need it. We also have the opportunity to call any third-party services directly from the method, without the need to subscribe to changes to the state.
Does this PR introduce a breaking change?