Dissecting Twitter’s Redux Store

If you don’t already know Twitter’s mobile website is on a new web stack which includes React and Redux 🎉.

After hearing the news I thought it would be fun to dig into their Redux store, and see how in the hell they organize all them tweets in their state tree.

NOTE: All observations are from me poking around in Chrome devtools and are at best educated guesses onto what’s happening in the app.

To get a look at the Redux store you will need React Developer Tools (RDT) installed for Chrome. Then from the RDT tab select the root element of the application and type the following in your console.

// $r is a shortcut that references the selected element in RDT
Thanks Wes Bos for tweeting out the tip on the above.

You should see the Redux state tree logged to the console like this…

I recommend taking the time to poke around all the different state slices, but I’m going to be digging into entities/tweets and homeTimeline. These two slices appear to contain the majority of the tweet related data.

All the detailed tweet data is stored under entities/tweets/entities in a normalized data table where each tweet is an object with id as the key and all the tweet data as the value. I have expanded the first tweet in the list so you can get a look at the guts of the tweet.

Your Twitter timeline is represented by the homeTimelines/timeline state slice. The timeline order follows the order of the array where the item at index zero is the first item in your timeline. Each tweet in the timeline has a tweet id that matches the key from entities/tweets/entities data table. This is pretty much normalizing state shape 101 from Dan Abramov — see they don’t make this shit up.

The timeline seems to track tweets by top and bottom, where top = new tweets, and bottom = older tweets. The lastFetch.bottom and lastFetch.top hold a date stamp that represents the last time tweets were fetched for these two categories. As new tweets come in they will be loaded at the top, where as bottom tweets will come in as your scroll further down your timeline.

The cursor.bottom and cursor.top reference a tweet id, which references the tweet currently holding the top/bottom positions in the timeline.

Lastly one more interesting thing, if you look under the entities slice again you will notice in addition to tweets you have cards, lists and users. All four of these items follow the same structure when you expand them, and include a fetchStatus. This again contains a data table where the key is tweet id, and the value appears to be the fetch status — in my case all tweets are “loaded”. I can only guess at what the other statuses are as I was never able to get a breakpoint in that let me see the status in a non-loaded state. Assuming that there is a “loading” status you could use that for the following:

  1. Ensure duplicate requests for the same tweet don’t go to the server if a tweet is already being fetched or “loading”.
  2. Allow rendering to start on the timeline without needing the detailed tweet payload from entities.

That’s all I got for now…

I encourage anyone who is interested in Redux to poke around this app on their own, as there is a lot of great stuff in there. I must say it is refreshing to see Redux being used on a webapp of this scale.

So, the next time you’re dealing with a Redux nay-sayer save your breath and just point them at this site. 😉