Saturday, March 20, 2021
NGRX Normalization
Application state is the data required to render the views over time.
One of the conceptual difficulties that makes Ngrx difficult is how to structure the state. There is no one answer because the source, usage and modification of the state is different in every app.
This is how I approach it.
The path between the api and components represents a series of Ngrx actions and functions. This is one direction of the data flow.
- The component dispatches an action
- An effect watches for that action and runs an http call that fetches the data
- On success a second action is dispatched containing the data
- The reducer responds to the action and updates the state
- A selector emits the data in a shape useful for the component
- The component renders the view.
The first three are simply the mechanics of sending a command and having it execute. The last two, the selector and component render are what determines what you do in 4, the reducer.
Something I've been working on recently illustrates the challenge. I have a component with a map, a table and a day selection component for viewing the locations and routes in a workday of a service tech. The data comes from gps logs, in different formats and different levels of detail. Some are simply a list of time and locations, others are the result of analysis and have lists of routes and places.
Much of the grunt work of assembling the data is done on the server, and the client gets an array of routes and stop points. The goal of the component is to come up with timesheet data, travel distances for expenses, and billing information for the services rendered; when and where and how long.
The three components render different aspects of the data.
- The day selection component renders the selectedday, which comes from the router url.
- The map renders routes and stop points, using the map functions and classes.
- The table lists the same routes and stop points, with duration, distance, at a specific location identified as an address and/or business location.
The selectedday is driven by the UI; the user selects the day or passes the day via the url. A change of day dispatches an action which fetches the location data for that day.
The map selector gets the list of routes and places, builds the map classes. The component subscribes and attaches the UI callbacks.
The table selector puts together a list extracted from each location item in the state, with duration, distance and any other data that is available.
Imaging the data flowing and being modified from the server => effect => reducer => state => 3 selectors. If the reducer processed the data into the map classes, the table wouldn't get what it needs. Same if the reducer processed the data into the shape that the table required. There is a point in that line of modifications before it branches for the three selectors, and that is what you want your reducer to put in the app state.
If you are only viewing the data, this point is usually quite simple to figure out. But what if you are editing the data?
Subscribe to Posts [Atom]