Keep your Large Redux Application In Check with Redux-Usage-Report
One of the refreshing things about moving to Redux from other types of state management is how easy it becomes to understand what’s going on in your app. You can use Redux Devtools to get a complete picture of the current state, and trace the series of actions that got it there. It’s all in one place, in a single object tree. Everything seems so much more transparent than before.
As your app grows, however, and multiple developers work on features that add more and more data to the store, things can start to get foggy again. Maybe some data is being passed down from the server, but no longer actually used, bloating the store. Or maybe the entities aren’t fully normalized, leading to confusing duplication. Sometimes, it’s simply difficult to discern which components are accessing which parts of the store, or to get a clear sense of how data is flowing through the app.
Codecademy was an early adopter of Redux and, as our app has matured, we’ve dealt with some of these problems. Recently, as I was refactoring part of our store, I started wishing for a tool that would tell me exactly which parts of the Redux store were being used in any given view, and which parts of the store remained completely untouched by the app. Ideally, I also wanted a way to pause code execution when certain parts of the store were accessed, so I could see exactly how our React component tree related to the Redux state tree.
I looked around for such a tool, but my search came up empty. So I decided to build it myself — a store enhancer that outputs a report of your Redux usage, aptly named redux-usage-report.
Let’s look at how you might use it to audit your Redux store.
Practical Guide to using Redux-usage-report
Here’s an example based on a time I wanted to investigate whether the data being passed down from the server in a certain
courseProgresses entity was actually used in a particular view of our app.
1. Add the store enhancer
redux-usage-report package and add the store enhancer according to the instructions.
2. Generate the report
Load the app, perform any user interactions you want to register, and then call
reduxReport.generate() in the browser console.
3. Inspect the
unused part of the report
unused object returned by the report shows which parts of the store were never accessed. (All screenshots are from the Chrome devtools).
Here, for instance, I see that quite a lot of the
courseProgresses data wasn’t needed to render the current view of a course listing page. (If a key is null, that means everything underneath it was not accessed.) It seems that I might want to investigate whether some of the data might be redundant for rendering the current view.
4. Inspect the
used part of the report
But which parts of the
courseProgresses entities were actually required to render the current view? To answer that question, I can inspect the
used key of the report to see which parts of the store were accessed at least once:
It seems clear enough that, for the courses that were actually rendered for this page, the only parts of the
courseProgresses entity accessed were the
started key, and, if that was
true rather than
percent_complete key as well.
5. Set a breakpoint
Say I want to see exactly when the
started key is accessed. To do this I can type the following in the console:
After I reload the page, execution will be paused when that value is accessed, and I’ll be able to go down the call stack and see where it’s used.
Here, I see that the
percent_complete object is passed to the
TrackedCourseCard component as a prop called
How it works
Quick Proxy Interlude
To quote MDN’s proxy page,“The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).” Here’s a brief code snippet demonstrating how a very basic proxy works. This one just logs any usage of an object to the console.
Redux-usage-report uses proxies, along with some extra code to keep track of what has been accessed. If you’d like to take a look at the full implementation of the library, you can check it out here.
That’s about all there is to using
redux-usage-report. It might be overkill to use it on a small Redux project or one with few developers, but if you are loading a lot of data into your app up front, or if you have a large store and want a better idea of which parts of it are accessed when, give it a try!
Want to learn more about how we use Redux at Codecademy? Check out my colleague Jon Samp’s article on making the switch to Redux-First-Router.