Using Redux in Angular to call an ASP.NET Core Backend
So it’s not 2020, why do you now (still) write articles about Angular and Redux? Well basically… Because it’s awesome. I did this talk about Angular and Redux at some conferences a couple of years ago so the content in the blog is nog bleeding edge. However, still I see a lot of solutions built in Angular that could have been solved way easier. Welcome to this demo…
What is Redux
Redux as a state store, or state management system if you like. So it basically maintains the state of your system or sub-systems. Redux came from the React world. Since I’m a backend developer and I know my way pretty well in Angular I don’t feel the need to learn React. Angular is just my personal favorite, I can do anything I want with it so there’s no need to learn a different framework for me. If you like React, Vue, or whatever alternative over Angular I’m totally fine with that.
The problem
The problem Redux solves is that we need to maintain the state of an object (in this demo, a list filter) but there are many components that influence the state of the filter. For example the address bar of the browser. When users change that and add a filter for example ?paramtername=parametervalue
, the filter must be changed. On the list page, there are a number of controls that should set one or more properties as well, and they need to update each other. To do this, you need to raise a lot of events. These events are handled and update a certain component, which in turn raises a new event, updating the other controls again. It’s easy to get stuck in a huge chain reaction of events, while you only update one filter field.
The solution
Redux solves this problem for you. It is the one and only one entity allowed to change the state of (in this case) the list filter. You’re able to subscribe to changes of the filter so once the filter is changed, Redux will let you know. By sending actions to Redux, I let it know what’s happening so it can then update the state accordingly.
The backend
So the backend is a fairly simple ASP.NET Core 3.1 API. To create one yourself, you can use Visual Studio or the dotnet
CLI. I added some fake data of car tires. The API contains two endpoints, one to list all the tires, and one to remove a single tire from the list. You can add parameters to your backend call to filter the list.
The frontend
The frontend project is an Angular project with some Angular Material to make everything look nice and (of course) Redux. To run this project, you need to have NodeJS 12.x or higher installed. Once you downloaded or cloned the project it’s wise to install the Angular CLI. Open a command window (like Windows Terminal) and type npm i @angular/cli -g
. Wait for the process to complete and you’re good to go. Now navigate to the root of the frontend project. The frontend project contains a couple of packages that need to be installed to be able to run the project. Type npm i
, wait some time… and you’re good to go.
Configuration
If you run the backend project, you’ll see the URL where you can reach it. In my case, it’s https://localhost:44398
. You need to copy and paste this value in the configuration of the frontend project. Open a file src/environments/environment.ts
and you’ll see a parameter backendUrl. Replace its value with your backend URL. Be sure to remove any trailing slash.
Now you’re good to run the project. So again, using a command window in the root of your frontend project type ng serve -o
. This ng
is an Angular CLI command and serve
means, build this project en run it in a development environment. The -o
means that when done, open a browser and navigate to my project. And I assume, that your backend project is still running as well ;)
The nifty part
Now for your introduction to Redux, open the frontend project with your favorite editor, and navigate to the /src/app/state
folder. This is where all the redux magic happens. There’s an app.state.ts
which contains all the state components in the project. In this case only one important, the CatalogState
. Now one folder deeper in the catalog
folder you will see a couple of files that drive the Redux part of this list filter state.
The actions file contains a definition of all actions that can possibly be executed within the scope of the list filter. The effects file contains side effects that need to occur whenever an action was executed. Side effects are optional, but ideal for (for example) backend calls.
The ‘models’ file, contains models that I like to use for both backend communication and/or data binding and stuff. Not really Redux related.
Then the reducer file is responsible for maintaining the object state. Because the state in Redux is immutable, the reducer will create a new version of the state and overwrite the old state with a new version.
Finally, the state file is a definition of all the data I want the state store to store.
Using Redux
Now if you navigate to the catalog
module (/src/app/pages/catalog
) you’ll see all the pages and components used for the list page. For example, if you see open the list itself (catalog-list-page.component.ts) you’ll see a lot of subscriptions to changes in the store. For example, in case the list got updated from the server, make sure the new values are shown in the list.
Also, note that in the ngOnInit()
function a subscription is made to the list filter change. This immediately dispatches a new action to update the list content.
this.filterChangedSubscription = this.store
.select((str) => str.catalogState.listFilter)
.subscribe((val) => {
if (!val) {
this.readRouterParams();
} else {
this.store.dispatch(new CatalogList(val));
this.queryStringService.setQuerystringParameters(val);
}
});
The code above subscribes to the list filter. Once the filter has changed, a new action will be dispatched, making a call to the Backend API and updating the list, and also to update the query string parameters in the address bar of your browser. The subscription doesn’t care about who changed the list filter, but apparently it changed, so I need to do something.
Excuting actions
When you want to execute an action, for example, a filter value is updated and you want Redux to update the value, you can dispatch an action. The catalog-list-filter.component.ts
file contains a couple of those dispatch actions to update the filter state for each possible field.
Conclusion
I think Redux is a pretty powerful tool to use writing your frontend solutions. I also know there are a couple of alternatives available that do more or less the same. It’s not that I’m tied to Redux, but the concept is awesome. Even tiny projects leverage its capabilities. For larger projects, I think working without some kind of state store is out of the question.