-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
docs: add exported reducer function to createReducer examples #1924
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ There are a few consistent parts of every piece of state managed by a reducer. | |
|
||
- An interface or type that defines the shape of the state. | ||
- The arguments including the initial state or current state and the current action. | ||
- The switch statement | ||
- The functions that handle state changes for their associated action(s). | ||
|
||
Below is an example of a set of actions to handle the state of a scoreboard, | ||
and the associated reducer function. | ||
|
@@ -36,6 +36,7 @@ a shape for the piece of state. | |
Each reducer function is a listener of actions. The scoreboard actions defined above describe the possible transitions handled by the reducer. Import multiple sets of actions to handle additional state transitions within a reducer. | ||
|
||
<code-example header="scoreboard.reducer.ts"> | ||
import { Action, createReducer, on } from '@ngrx/store'; | ||
import * as ScoreboardPageActions from '../actions/scoreboard-page.actions'; | ||
|
||
export interface State { | ||
|
@@ -64,26 +65,42 @@ The initial values for the `home` and `away` properties of the state are 0. | |
|
||
### Creating the reducer function | ||
|
||
The reducer function's responsibility is to handle the state transitions in an immutable way. Define a reducer function that handles the actions for managing the state of the scoreboard. | ||
The reducer function's responsibility is to handle the state transitions in an immutable way. Create a reducer function that handles the actions for managing the state of the scoreboard using the `createReducer` function. | ||
|
||
<code-example header="scoreboard.reducer.ts"> | ||
export const reducer = createReducer( | ||
initialScoreState, | ||
const scoreboardReducer = createReducer( | ||
initialState, | ||
on(ScoreboardPageActions.homeScore, state => ({ ...state, home: state.home + 1 })), | ||
on(ScoreboardPageActions.awayScore, state => ({ ...state, away: state.away + 1 })), | ||
on(ScoreboardPageActions.resetScore, state => ({ home: 0, away: 0 })) | ||
); | ||
|
||
export function reducer(state: State | undefined: action: Action) { | ||
return scoreboardReducer(state, action); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will only work for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. I think that should be an additional section to talk about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Haven't found any. Is it somewhere I missed? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maxime1992 there's an open issue - #1179 |
||
</code-example> | ||
|
||
In the example above, the reducer is handling 3 actions: `[Scoreboard Page] Home Score`, `[Scoreboard Page] Away Score`, and `[Scoreboard Page] Reset`. Each action is strongly-typed. Each action handles the state transition immutably. This means that the state transitions are not modifying the original state, but are returning a new state object using the spread operator. The spread syntax copies the properties from the current state into the object, creating a new reference. This ensures that a new state is produced with each change, preserving the purity of the change. This also promotes referential integrity, guaranteeing that the old reference was discarded when a state change occurred. | ||
<div class="alert is-important"> | ||
|
||
**Note:** The exported `reducer` function is necessary as [function calls are not supported](https://angular.io/guide/aot-compiler#function-calls-are-not-supported) by the AOT compiler. | ||
|
||
</div> | ||
|
||
In the example above, the reducer is handling 3 actions: `[Scoreboard Page] Home Score`, `[Scoreboard Page] Away Score`, and `[Scoreboard Page] Score Reset`. Each action is strongly-typed. Each action handles the state transition immutably. This means that the state transitions are not modifying the original state, but are returning a new state object using the spread operator. The spread syntax copies the properties from the current state into the object, creating a new reference. This ensures that a new state is produced with each change, preserving the purity of the change. This also promotes referential integrity, guaranteeing that the old reference was discarded when a state change occurred. | ||
|
||
<div class="alert is-important"> | ||
|
||
**Note:** The [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) only does shallow copying and does not handle deeply nested objects. You need to copy each level in the object to ensure immutability. There are libraries that handle deep copying including [lodash](https://lodash.com) and [immer](https://github.com/mweststrate/immer). | ||
|
||
</div> | ||
|
||
When an action is dispatched, _all registered reducers_ receive the action. Whether they handle the action is determined by the switch statement. For this reason, each switch statement _always_ includes a default case that returns the previous state when the reducer function doesn't need to handle the action. | ||
When an action is dispatched, _all registered reducers_ receive the action. Whether they handle the action is determined by the `on` functions that associate one or more actions with a given state change. | ||
|
||
<div class="alert is-important"> | ||
|
||
**Note:** You can also write reducers using switch statements, which was the previously defined way before reducer creators were introduced in NgRx. If you are looking for examples of reducers using switch statements, visit the documentation for [versions 7.x and prior](https://v7.ngrx.io/guide/store/reducers). | ||
|
||
</div> | ||
|
||
## Registering root state | ||
|
||
|
@@ -92,11 +109,11 @@ The state of your application is defined as one large object. Registering reduce | |
<code-example header="app.module.ts"> | ||
import { NgModule } from '@angular/core'; | ||
import { StoreModule } from '@ngrx/store'; | ||
import { scoreboardReducer } from './reducers/scoreboard.reducer'; | ||
import * as fromScoreboard from './reducers/scoreboard.reducer'; | ||
|
||
@NgModule({ | ||
imports: [ | ||
StoreModule.forRoot({ game: scoreboardReducer }) | ||
StoreModule.forRoot({ game: fromScoreboard.reducer }) | ||
], | ||
}) | ||
export class AppModule {} | ||
|
@@ -134,11 +151,11 @@ Now use the `scoreboard` reducer with a feature `NgModule` named `ScoreboardModu | |
<code-example header="scoreboard.module.ts"> | ||
import { NgModule } from '@angular/core'; | ||
import { StoreModule } from '@ngrx/store'; | ||
import { scoreboardReducer } from './reducers/scoreboard.reducer'; | ||
import * as fromScoreboard from './reducers/scoreboard.reducer'; | ||
|
||
@NgModule({ | ||
imports: [ | ||
StoreModule.forFeature('game', scoreboardReducer) | ||
StoreModule.forFeature('game', fromScoreboard.reducer) | ||
], | ||
}) | ||
export class ScoreboardModule {} | ||
|
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.
I can't highlight it but on line 15, we define the reducer function with
- The switch statement
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.
Fixed