Flux example Application with React JS

Flux has three main parts.

  1. Action
  2. Dispatcher
  3. Store
As their name indicates, Action is the result of some events, like JavaScript events, or callbacks for Ajax calls. Dispatcher, is a connector or link between Action and Store. The dispatcher is a central hub, from where everything passes through and we only need one dispatcher per application. Dispatcher handles all Actions and Stores. Store is very important in Flux architecture, we can write our business logics or Ajax calls to fetch data’s. I usually use it to store to get some initial data’s or to send or receive data via Ajax calls. The store uses event emitter similar to nodejs’s event emitter. We can define events in Store, and these events are connected to Store, whenever a change occurs in store, all components which listenes to this store will get an invoke and we can perform our logics. My example application will give you more idea, you can clone it from my GitHub account. In this application I have an input box where you can enter the number and a button to ‘Add Cart’, we can start from this button, this button has an on Click event, I have attached a Flux action on it, whenever a change occurs it passes input box data to an action.

Component

import React from 'react';
import checkoutActions from "../actions/checkout-action";
import checkoutStore from "../store/checkout-store";
class CartElements extends React.Component{
  constructor(){
    super()
    this.state = {
      currentCart : checkoutStore.getCart()
    }
  }
  componentDidMount(){
    checkoutStore.addListener(this.updateCartNumber)
  };
  updateCartNumber = () => {
    this.setState({
      currentCart: checkoutStore.getCart()
    })
  };
  updateCart = () => {
    checkoutActions.addCart(parseInt(this.refs.cartNumber.value))
  };
  gotoCheckout = () => {
    window.location.href +="?products=[1,2,3]"
  };
  render(){
    var checkoutButton = "";
    if(this.state.currentCart > 0){
      checkoutButton = <a className="button" href="/welcome/checkout?products=[1,2,3,4]">CheckOut</a>;
    }
    return(
      <div>
        <div className="input-group">
            <input type="number" ref="cartNumber"/>
        </div>
        <button className="button success" onClick={this.updateCart}>Add to Cart</button>
        {checkoutButton}
      </div>
    )
  }
}
export default CartElements

Action File

import dispatcher from "../dispatcher";
import constants from "../const/store-const";
var checkoutActions  = {
  addCart: function(data){
    dispatcher.dispatch({
      actionType: constants.ADD_CART,
      data: data
    })
  }
}
export default checkoutActions;
  In this Action, I have an addCart  method which dispatches item quantity along with a constant called ‘ADD_CART’ which is used to distinguish it on Store. Dispatcher is a simple file which uses Facebook dispatcher Object Assign is a NPM module where you can combine two objects and return source object, For example var birds = {bird:”Pigeon”} var animals = {animal:”Dog”} assign(birds, animals) => {bird:”Pigeon”, animal:”Dog”} We have a Store called checkStore, for which we have 5 methods. First 2 of them are custom methods, addCart and getCart. When we call Addcart, it increases the quantity and getCart to retrieve the latest value. Besides we have 3 required methods
  1. emitChange
  2. addListener
  3. removeListener
import dispatcher from '../dispatcher.js';
import EventEmitter from 'events';
import assign from 'object-assign';
var CHANGE_EVENT = 'change';
var EventEmitterEvent  = EventEmitter.EventEmitter
var _number  = 0;
var checkoutStore = assign({}, EventEmitterEvent.prototype, {
  addCart: function(number){
    return _number = _number + number;
  },
  getCart: function(){
    return _number;
  },
  emitChange: function(){
    this.emit(CHANGE_EVENT)
  },
  addListener: function(callback){
    this.on(CHANGE_EVENT, callback)
  },
  removeListner: function(callback){
    this.removeListner(CHANGE_EVENT, callback)
  }
});
dispatcher.register((action)=>{
  switch (action.actionType){
    case 'ADD_CART':
      console.log("hello")
      checkoutStore.addCart(action.data)
      checkoutStore.emitChange()
      break;
  }
})
export default checkoutStore;
  AddListener adds EventListner. We can use this to bind events to components. RemoveListener is used to remove listeners when we unmounts some components. EmitChange is used to update or invoke store after some actions. The store also has a dispatcher, where we register dispatcher, and in action, we dispatch data to stores. All data which passes from action is available in action argument, the switch uses check actionType, we already pass a constant from action to distinguish various types, like CREATE, EDIT, DELETE, and here we have ADD_CART, so only particular block works. In this case, we have only one condition inside switch block and condition with ADD_CART will work. Inside this condition we call add_cart store method and pass quantity after which we can emitchange. So, this store will invoke and all components which are connected will notify. Now we can move to a header component. There is a component called CartIconOnTopBar, in componentDidMount.I have attached a Store listener, ‘checkOutStore.addListener(callback)’ with a callback function, in this callback function, I again called stores getCart function to get latest items quantity.
class CartIconOnTopBar extends React.Component{
  constructor(){
    super()
    this.state = {
      cartItemCount: checkoutStore.getCart()
    }
  }
  componentDidMount(){
   checkoutStore.addListener(this.updateCart)
  };
  updateCart = () => {
    this.setState({
      cartItemCount: checkoutStore.getCart()
    })
  };
  openClassModal = () => {
  };
  render(){
    return(
        <li>
          <a href="#" onClick={this.openCartModal} className="cart-element">
            <i className="fi-shopping-cart"></i>
            <span className="cart-count"> {this.state.cartItemCount} </span>
          </a>
        </li>
    )
  }
}
When we click on button, it passes data to action and through dispatcher it reaches store and it invokes store and all components which connected to this store will notify and it run callback functions and then we can update our data’s. In this application for a demonstration you can add as many actions and store. This is only a basics of flux, there are more in flux, also, flux has some alternatives like redux.]]>