Leveraging Reflux (flux) with React like a pro

#Leveraging Reflux (flux) with React like a pro

My latest project for a well known clothing retailer has involved writing a React based web app. It has a staggering amount of data that needs to update different parts of the app. To accomplish this, we are using React (of course) and Reflux.

So you’ve heard React is the new hotness that all the cool developers are adding to their resume. It’s supposed to cure all your front-end woes. But in fact, you’ll find yourself with some new hand wringing problems to get you down. Don’t Fret. There is a better way.

Flux is not so much a software, but a way to keep data synchronized in your front-end app. What am I talking about? Say a person enters some data into a form and presses Send, we need to keep that data in sync in other parts of the app. Reflux is just a re-invention of the flux concept with some powerful features and simplified tools.

A simplified diagram of data flow 

╔═════════╗       ╔════════╗       ╔═════════════════╗
║ Actions ║──────>║ Stores ║──────>║ View Components ║
╚═════════╝       ╚════════╝       ╚═════════════════╝
     ^                                      │
     └──────────────────────────────────────┘

The major players 

  • The React component (View Component)
  • The Reflux Actions file
  • The Reflux Store file

Think of this one way data flow like this. The component says “Hey, the person has updated their name in an input field”, so it calls the action that is defined in the Action file. The Action takes care of sending out a broadcast with the data the person entered. The Store is listening to the Actions file and gets called, it updates itself and then triggers an update. The component is listening to the Store and updates itself because it has new state values.

A simple web form 

FirstNameHeader.js (For displaying the name entered into the input) 

import React from 'react';
import Reflux from 'reflux';
// We import the PersonStore so we can get its value and updated when it's updated
import PersonStore from './PersonStore.js';

export default React.createClass({
  mixins: [
    /* The value of the PersonStore is set in the local state as 'person' */
    Reflux.connect(PersonStore, 'person')
  ],
  renderer() {
    return (
      <h1>{this.state.person.first_name}</h1>
    );
  }
});

FirstNameInput.js 

import React from 'react';
import Actions from './Actions.js';

export default React.createClass({
  renderer() {
    return (
      <input type="text" name="first_name" defaultValue="" onChange={this._onUpdate}  />
    );
  },
  _onUpdate(event) {
    let name = event.target.name;
    let value = event.target.value;
    // `updatedPerson` is defined in Actions.js, and PersonStore.js has a `onUpdatePerson` method that matches the following
    Actions.updatePerson(name, value);
  }
});

Actions.js 

import Reflux from 'reflux';

// This file is small, but essential
export default Reflux.createActions([
  'updatePerson'
]);

PersonStore.js The data store for person data 

import Reflux from 'reflux';
import Actions from './Actions.js';

let person = {
  first_name: ''
};

export default Reflux.createStore({
  // This is magic that matches up the Actions to the listening methods below
  listeners: Actions,
  init() {
    // Need to provide the initial value to compenents
    return person;
  },

  // A `magic` method that matches up to the `updatePerson` Action
  // This is called in our `FirstNameInput.js` file
  onUpdatePerson(name, value) {
    person[name] = value;

    // Needed for any component listening to these updates
    this.trigger(person);

  }
});

So what does this lame web app do? Why so complex? 

Glad you asked. When a person enters their name in the input, the change is reflected in the header component. But wait, you could add another component that would also be able to get those updates too. Later we’ll see how you can combine multiple Actions and Stores to create powerful workflows for your data.

I admit, the documentation for Reflux is lacking and not very easy to follow, but it’s a very powerful and elegant framework for keeping state across components. We’ve found it essential to building a very complex React web app.

Disclaimers 

  • I’m using ES6 in my examples
  • Reflux has several different ways to skin a cat, this is the one of the simple more magical ways
  • We’ll cover async actions in a different post

Did this help you out? It took me a few days to piece together all this information together, I hope this saves you some time (who knows, maybe the future me will be thankful I wrote this down). Let me know your thoughts. shanestillwell@gmail.com