As we reviewed dashboard V2 while working on V3, state management showed up as the biggest issue. For example on our live page we show the last know location of all the drivers. This UI state would need to refresh based on multiple actions – selecting a fleet, selecting status tabs, selecting a driver or explicitly hitting the refresh button at the bottom of the map. Because the state could be altered by so many events, it became difficult to handle race conditions and edge cases to provide a consistent view.
Angular allows you to create singletons using services and dependency injection, which can be used for state management. We realised having a single source of truth for the UI state would solve a lot of our problems. Every event needs to change the state object first which will then get reflected on the UI. So in our
drivers.service.ts , we created a
Subject which acted as the state of the UI. Let me explain what is
Subject is an
rxjs entity to which you can push values (
subject.next(value) ) and also gives you a listener (
subject.subscribe(successFn)) to get the latest value.
All this looked a lot like redux. Redux also works by creating a single state object and the UI state reflects just this single source of truth.
Redux is more of an architecture for state management than a library. ngrx/store is implementation of redux for angular which we used in our app. It does a pretty good job of combining the power of rxjs with redux.
We need to define state interface like the following code snippet and assign a reducer function for different state properties. We will talk about reducer function in a bit.
ngrx internally uses a type of
Subject which needs be instantiated with an initial value. Its called
We can listen to these states just by subscribing to state object.
The state can be changed by dispatching an action. An action consists of type and payload which can be any form of data.
Reducer function, which we defined with the state interface earlier, runs every time an action is dispatched. In this function we return next state using the current state and the action. It internally calls
store.next(state) which emits the new state to all the subscribers.
This reducer function is the heart of redux. It is a single place where state can be altered. Here it is essential to make sure that we don’t mutate the state in the reducer function, instead we should create a new state object. Otherwise the
ngrx would not emit change to the subscribers.
Though it might look too much like a boilerplate to achieve a simple task, it solves the state management issue for a moderately large app.
Implementing redux in our angular app greatly reduced bugs and helped us maintain a consistent UI state by doing state management for us. I feel more confident building new features faster because of predictability of the app. I would highly recommend
ngrx/store and redux.
Like what we are working on? Come work with us, we are hiring!