A year ago I started working as a web developer at Trade Me. I found myself in a team working on a large scale, single page application that is built using Angular.

When building a large application that has lots of information coming from and going to the database as well as data that is shared across multiple components, things can easily get messy and complex. Our app has a lot going on in it and one of the challenges is figuring out how to manage data and maintain the UI state of the app.

To achieve this, our app uses @ngrx/store — a state management library for Angular applications inspired by Redux. By using this library we are able to keep the current state of the app in one place — the store. This enables us to use the store as a single source of truth meaning we can reliably access the state of the app from this one place rather than components of the app holding their own state and having to communicate and pass data between them. This reduces the communication between components which is particularly helpful to scale our app without adding more complexity.

Having the store on the client also allows us to use it as a local cache of data. Our app can render items instantly if they already exist in the stored state without having to resend an API request.

Using the Redux pattern also prevents the mutation of state in multiple locations in our app. Data is changed in one central location and flows one way from this location to the UI components. All the components in our application follow this pattern which helps us keep our app more predictable and easier to understand.

And as an added bonus, the Redux pattern helps us keep our components fairly simple which makes testing them straight forward.

Using @ngrx/store in our app

If you look online, there are some good resources for learning about how to use @ngrx/store in an Angular application and lots of diagrams that are helpful to understanding the concept of state management. These often mention the store, actions and reducers. All which are key concepts to understand. However when first trying to work out what is going on in the code base of our app, it seems to have a bit more going on. Things like effects, selectors and things our team calls facades.

With lots of different files and lots of different names it has taken a while to understand how these all work together. The following is a guide to how these things fit into the structure of our app.

The basic structure of Redux looks like this:

The core principles of Redux. These include the component, the action, the reducer and the stored state.

The component is what the user can interact with. For example, a search input box the user can fill out and submit via a clickable button. When the button is clicked we dispatch an action to the store.

The action describes the change in state that is to be made.

This action is sent to the reducer which is a pure function — it takes the data from the action and the current state and generates the new state from it. Each reducer is specific to only a small part of the state.

For example, the state might look like:

search: {

search: oldSearchResults

},

listings: {

listing: […]

},

otherThings: {

things: otherData

}

A new search action is dispatched and the reducer takes the previous search state and updates it to the new state with the latest search info. In this example this is done by the search reducer which is specifically in charge of updating the search part of the stored state with the new data.

The stored state would now look like:

search: {

search: newSearchResults

},

listings: {

listing: […]

},

otherThings: {

things: otherData

}

Once the store is updated with the new state from the reducer, we can then update the components with this new state.