You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/chapter-5.mdx
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,14 +27,15 @@ This is an action that adds a category named `Food` to the list of all categorie
27
27
```ts
28
28
// src/app/state/actions.ts
29
29
import { createAction, props } from"@ngrx/store";
30
+
import { Category } from"./state";
30
31
31
32
exportconst addCategory =createAction(
32
33
"[Category List] Add Category",
33
-
props<{ name:string }>()
34
+
props<{ category:Category }>()
34
35
);
35
36
```
36
37
37
-
Let's break down this example. First of all, the name `createAction` is a bit deceptive; it does not create an action; in fact, it creates a function which, when called, wil produce an action object. The first argument is the `type` of the action that will be produced. When called, the `addCategory` function will **always** create an action with type "[Category List] Create Category". The second argument uses the bizarre function `props`, which is a generic function that allows us to define the type of the `payload` which the created action will have. Essentially, it explains that in order to create the action using the `addCategory` function, we should call it and provide an object that has a property `name` which is a `string`. Let's do this and `console.log` the result.
38
+
Let's break down this example. First of all, the name `createAction` is a bit deceptive; it does not create an action; in fact, it creates a function which, when called, wil produce an action object. The first argument is the `type` of the action that will be produced. When called, the `addCategory` function will **always** create an action with type "[Category List] Create Category". The second argument uses the bizarre function `props`, which is a generic function that allows us to define the type of the `payload` which the created action will have. Essentially, it explains that in order to create the action using the `addCategory` function, we should call it and provide an object that has a property `category` which is defined in the Interface Category defined in the AppState. Let's do this and `console.log` the result.
38
39
39
40
```ts
40
41
// src/app/app.component.ts
@@ -47,15 +48,15 @@ import { addCategory } from "./state/actions.ts";
So essentially, `createAction` provided us with an easy way of creating actions of the same type. `addCategory` in our case is an `ActionCreator`, a function which produces an action object whenever called, and `props` explained what argument that `ActionCreator` function expects.
> **_NOTE:_** Beware of the **payload** attribute of the Action, which only fits the "old" way to create actions. Next example will use the props and call directly the properties added to the Action.
93
+
92
94
Now let's deconstruct this example. First of all, as you see, the `reducer` function is a pure function. Next, it differentiates between `Actions` using a `switch` statement and the `Action` types. On each different `Action`, our `Reducer` will return a slightly different version of a `State` to match that `Action`'s intent. As we have only one `Action` for now, we wrote only one `case` statement, and if the `Action` is not identified, we return the `state` without modifying it. As you can see, the practice is to copy the state, and return a new object. **Never modify the previous `state` object, always return a new one**.
93
95
What will happen is when we dispatch the `addCategory``Action`, the `reducer` function will be called, the new `State` (with the added category object in the `categories` array) will be returned, and then NgRx will propagate that change to all of our components.
Let's understand what goes on here. First of all, we have the `createReducer` function, which does exactly that - creates the resulting `Reducer` function. It receives the initial state of the application, and then an arbitrary amount of handlers for each action (we provided only one, but we can (and will!) have lots of `Actions`, and thus. lots of `on` function calls). The `on` function receives an `Action` as the first argument, and a callback function as a second one, which acts like a mini-`Reducer` for only that specific `Action`. Thus, the need to write huge `switch` statements is eliminated. Now let's understand two specific parts of this code:
122
+
Let's understand what goes on here. First of all, we have the `createReducer` function, which does exactly that - creates the resulting `Reducer` function. It receives the initial state of the application, and then an arbitrary amount of handlers for each action (we provided only one, but we can (and will!) have lots of `Actions`, and thus. lots of `on` function calls). The `on` function receives an `Action` as the first argument, and a callback function as a second one, which acts like a mini-`Reducer` for only that specific `Action`. Thus, the need to write huge `switch` statements is eliminated. Note that the callback signature is (state, {category}) in which we [destruct](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#object_destructuring) the action passed in the second argument in order to only get the props. Now let's understand two specific parts of this code:
121
123
122
124
1._Why did we create a `_reducer` function only to call it in the `reducer` function?_ The thing is, in the next chapters we are going to register the `reducer` function in our `AppModule`, and because of how the Angular build process works, it does not allow including anonymous functions like the one returned by `createReducer`, only declared named functions. Thus we wrote a conventional function and called our `_reducer` from it. **Always create `Reducers` like this**.
123
125
2._Why didn't we `import` the `Action` we wanted by name, but rather did `import * as actions from './actions';`? Because we can easily have dozens of `Actions` that are handled in a single `Reducer` function, we would like to import them as a single object to avoid too cluttered imports.
0 commit comments