Skip to content
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

fix/feat(store): createReducer: on should not be overwritten #2103

Merged
merged 2 commits into from
Oct 3, 2019

Conversation

zhaosiyang
Copy link
Contributor

@zhaosiyang zhaosiyang commented Sep 1, 2019

createReducer should allow ons to take actions of same type and excute all ons to match the action dispatched

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

[x] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] Other... Please describe:

What is the current behavior?

If the following is configured and initial state is 0, if increase action is dispatched, the next state is 2, because the the second on has same action type as the first on, and the first on is overwritten.

const increase = createAction('[COUNTER] INCREASE');
createReducer(0, on(increase, state = state + 1), on(increase, state = state + 2))

(Indirectly) Closes #1956

What is the new behavior?

In createReducer, on should not overwrite previous ons if they have the same action types.

Does this PR introduce a breaking change?

[ ] Yes
[x] No

@zhaosiyang
Copy link
Contributor Author

I have added an example of the necessity of this behaviour here (#1956 (comment))

@ngrxbot
Copy link
Collaborator

ngrxbot commented Sep 1, 2019

Preview docs changes for e8aebae at https://previews.ngrx.io/pr2103-e8aebae/

createReducer should allow ons to take actions of same type and excute all ons to match the action dispatched
@zhaosiyang zhaosiyang force-pushed the create-reducer-same-action branch from e8aebae to dcc72ee Compare September 1, 2019 20:51
@ngrxbot
Copy link
Collaborator

ngrxbot commented Sep 1, 2019

Preview docs changes for dcc72ee at https://previews.ngrx.io/pr2103-dcc72ee/

@zhaosiyang zhaosiyang changed the title createReducer: on should not be overwritten bug(store): createReducer: on should not be overwritten Sep 2, 2019
@timdeschryver
Copy link
Member

I'm not sure if this is a "bug".
I think both options are viable, and we'll have to decide which behavior makes the most sense and is safest to use.

@zhaosiyang
Copy link
Contributor Author

I'm not sure if this is a "bug".
I think both options are viable, and we'll have to decide which behavior makes the most sense and is safest to use.

Yeah, it could be either feature or bug.

In my opinion, the on should simply mean "execute this function when this action is dispatched" regardless of any other settings. We thus decoupled ons in this way.

Some usage case for justifying this feature could be:

  1. Update some state (that I defined) whenever some library-defined action is dispatched, for example (@ngrx/store/init, '@ngrx/store/update-reducers )
  2. Create higher order reducers which inject some global ons: please see Docs: Add more explanation that you can only have one distinct action type per on function with createReducer #1956 (comment) for more detail

However, I can't think of any case that need to overwrite previous on if action type is the same.

@zhaosiyang zhaosiyang changed the title bug(store): createReducer: on should not be overwritten bug/feature(store): createReducer: on should not be overwritten Sep 2, 2019
@zhaosiyang zhaosiyang changed the title bug/feature(store): createReducer: on should not be overwritten fix/feat(store): createReducer: on should not be overwritten Sep 3, 2019
for (let on of ons) {
for (let type of on.types) {
map.set(type, on.reducer);
if (map.has(type)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do the composition on the fly here instead of storing arrays for a small perf bump in the generated reducer:

if (map.has(type)) {
  const reducer = map.get(type) as ActionReducer<S, A>;
  map.set(type, (state, action) => on.reducer(reducer(state, action), action);
}
else {
  map.set(type, on.reducer);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @MikeRyanDev for the great suggestion. I have pushed a commit. :)

@zhaosiyang zhaosiyang force-pushed the create-reducer-same-action branch from 685cb32 to 8b31906 Compare September 24, 2019 14:11
@zhaosiyang zhaosiyang force-pushed the create-reducer-same-action branch from 8b31906 to a32c101 Compare September 24, 2019 14:11
@ngrxbot
Copy link
Collaborator

ngrxbot commented Sep 24, 2019

Preview docs changes for 685cb32 at https://previews.ngrx.io/pr2103-685cb32/

@ngrxbot
Copy link
Collaborator

ngrxbot commented Sep 24, 2019

Preview docs changes for a32c101 at https://previews.ngrx.io/pr2103-a32c101/

@brandonroberts
Copy link
Member

@timdeschryver you have anymore thoughts on this?

Copy link
Member

@timdeschryver timdeschryver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good for me @brandonroberts
I believe we should follow-up with some docs changes, if I remember correctly it mentions that the on will be overwritten.

@brandonroberts brandonroberts merged commit 9a70262 into ngrx:master Oct 3, 2019
@zhaosiyang zhaosiyang deleted the create-reducer-same-action branch October 17, 2019 17:20
jordanpowell88 pushed a commit to jordanpowell88/platform that referenced this pull request Nov 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Docs: Add more explanation that you can only have one distinct action type per on function with createReducer
5 participants