pseudoramble
Understanding React - A Refactoring
Published on 2015-10-14 Modified on 2015-10-14

To see the changes discussed in this entry, check out this commit!

To see the Listen to Railroad Earth player running, check out this site!

Ever begin working on a set of code to get something working, only to realize that you can't make forward progress? That was me, while working on a side project .

See, my component named Player was trying to be quite smart. You can see the original version of the file here . Player was supposed to have the following features:

  1. Showed the typical HTML5 audio controls.
  2. The player would show the currently playing track
  3. Had the ability to go to the previous & next tracks in a playlist.
  4. If the player was left running, it would continue through the existing playlist.
  5. If a new playlist was selected, it would reload with said playlist and begin playing that instead.

As you can see and probably imagine, Player was trying to be way too smart for everyone's good:

  1. There was messy state to maintain.
  2. There were edge cases to be detected and dealt with.
  3. This component had no real sense of separation of concerns (code should serve one small set of purposes).

React + Flux are put together to organize this setup so you avoid the situation I ended up in. Using a Flux architecture, you tend to force most data manipulating & related logic in Stores. This leaves React components to typically be more simplified, and focused on rendering said data.

The refactor looked like this:

A more visual sketch of the refactor might look like this:

*User clicks next track*                                                              |-> (Reconfig setlist)
----------------                    ------------------                                -------------
|              |  onTrackFinished   |                | {actionType : TRACK_FINISHED}  |           |
| Player (jsx) | -----------------> | PlayerActions  | -----------------------------> | ShowStore | ----------
|              |                    |                |     (Via the Dispatcher!)      |           |          |
----------------                    ------------------                                -------------          |
^                                                                                                            |
|____________________________________________________________________________________________________________|
   (Emit an event to have the "root" component of the application update its state. Send props to Player.)

Once I had this realization, implementing new features (like previous/next, continuous playing of a setlist) became much more simplified. Keeping your concerns separated and only loosly connected really does work, to a degree.

In closing, I'll leave you with a few clues that you may need to refactor your React component(s):

  1. You use setState() like a boss and you're not quite sure why.
  2. There are a bunch of edge cases to handle in a component.
  3. You're playing bug whack-a-mole (you fix one bug, only to create two more) in a component.
  4. A component is doing lots of data manipulation.
  5. Basic functionality seems to be impossible to enhance.