React, Flux, State and Stores

user3687035 picture user3687035 · May 29, 2014 · Viewed 10.2k times · Source

I find the example todo flux app to be a bit lacking so I'm trying to get my head round things by developing an application to learn and experiment.

The application is a drag and drop fruit basket organiser. I have several baskets which can have various pieces of fruit dragged between them. You can highlight a piece of fruit by clicking on it and the last dragged item will remain highlighted.

Based on this I have 3 stores:

  • FruitStore
  • BasketStore
  • AppStateStore - To track last clicked and last dragged fruit

When a user action occurs a FruitAction is dispatched and handled by either the AppStateStore if the fruit has been clicked or all stores if the fruit has been moved to another basket.

The main AppView component listens to change events from both the FruitStore and the AppStateStore and re-renders.

My questions are:

  • Is this a good approach for this scenario?
  • Should the AppView be listening to multiple stores? How should I prevent the AppView from rendering several times in a row? Right now, when a fruit has been moved, both FruitStore and AppStateStore fire change events causing two renders in a row.
  • The Flux article on the React site shows the view dispatching an action object (e.g. AppDispatcher.dispatch(TodoActions.updateText()) ) but would it be better if the action dispatched itself (e.g. just FruitActions.moveBasket() ) and the AppView is left unaware of the AppDispatcher?
  • Currently only the AppView listens to the stores but should the individual Fruit components listen to the AppStateStore to re-render only themselves if they are to be highlighted?
  • Is there a more complete example of the Flux architecture or something similar?

Answer

Michelle Tilley picture Michelle Tilley · May 29, 2014
  • The approach sounds pretty solid. I would create completely different actions for every interaction, e.g. FruitClicked and FruitDragged could both be actions, and the stores would watch for the ones they care about.
  • AppView should listen to all the stores that it gets data from. If you call setState more than once in the same tick, React will intelligently merge them, so you're not actually rendering more than once.
  • The article on the React site does talk about actions that dispatch themselves under Creating Semantic Actions. In the code block a few scroll-lenghts up the page, you can see the code:

    _onDestroyClick: function() { 
      TodoActions.destroy(this.props.todo.id); 
    } 
    
  • The article also talks about which components should listen to stores in Listening to Changes with a Controller-View:

    We need a React component near the top of our component hierarchy to listen for changes in the store. In a larger app, we would have more of these listening components, perhaps one for every section of the page. In Facebook's Ads Creation Tool, we have many of these controller-like views, each governing a specific section of the UI. In the Lookback Video Editor, we only had two: one for the animated preview and one for the image selection interface.

    and

    Occasionally we may need to add additional controller-views deeper in the hierarchy to keep components simple. This might help us to better encapsulate a section of the hierarchy related to a specific data domain. Be aware, however, that controller-views deeper in the hierarchy can violate the singular flow of data by introducing a new, potentially conflicting entry point for the data flow. In making the decision of whether to add a deep controller-view, balance the gain of simpler components against the complexity of multiple data updates flowing into the hierarchy at different points. These multiple data updates can lead to odd effects, with React's render method getting invoked repeatedly by updates from different controller-views, potentially increasing the difficulty of debugging.

  • If you're interested in the flux architecture, you may be interested in Fluxxor (disclaimer: I wrote it), which (hopefully) helps build out a flux-based application. It has a dispatcher that's a little more robust and a few other changes (e.g. non-global stores/actions, React mixins) to make things a bit easier in many cases.