Jaakko Karhu
Jaakko Karhu

Reputation: 2386

Why is Dispatcher launching unnecessary events on Flux?

I have a React/Flux app with a view of following components:

I also have corresponding stores:

...and actions:

When pressing a button on subnav, both the feed and the subnav should be updated, setting right kind of feed and highlighting the active subnav element. I am succesful with this goal, but I am also launching an onChange event multiple times, also with header.js component, even though it should not be affected with the action.

In actions I am calling dispatcher like this:

AppDispathcer.handleViewAction({

  actionType: AppConstants.SUBNAV_SET_ACTIVE,
  _id: subnavItemId
})

...depending on the purpose, of course. My dispatcher looks like this:

handleViewAction: function(action) {

this.dispatch({ source: 'VIEW_ACTION', action: action }) }

In stores I have something like this for handling the dispatcher:

dispatcherIndex: AppDispatcher.register(function(payload) {

  var action = payload.action;

  switch(action.actionType) {

    case AppConstants.FILTER_SET_CAT:

        FeedStore.selectVisibleFeedItems();
      break;

    case AppConstants.FEED_SHOW_MORE:

        FeedStore.showMoreItems(filterCatName);
      break;
  }

  FeedStore.emitChange();

  return true;
})

All the components have following functions (but with different listener names):

  componentWillMount:function(){

    FeedStore.addFeedListener(this._onChange, 'feed-area.js');
  },

  componentWillUnmount:function() {

    FeedStore.removeFeedListener(this._onChange)
  },

  _onChange: function(){

    this.setState(getVisibleFeedItems())
  },

Now when the desired action happens, _onChange is launched on all: header, subnav-area and feed-area components.

Where do I start looking for the bug? I don't fully understand how the dispatcher works, should I somehow separate the functions for handling the view? I thought Flux somehow listens the stores and updates views according to it, now it seems it is listening something else and I don't really understand what.

Upvotes: 2

Views: 143

Answers (1)

Oscar Linde
Oscar Linde

Reputation: 528

I'll begin describing an example of the general idea and then go on how you could debug things.

Let's say i have a Shopping Cart and a Item Component.

Whenever an add event is fired from the Item component it should trigger an Action which, lets say, make an AJAX request to your server and then dispatch an event called CART_ITEM_ADDED(In your case i guess you would do Dispatcher.handleViewAction('CART_ITEM_ADDED'). The dispatcher would tell it's subscribers that an event was received and each subscriber would see if it's interested in that event. The subscriber(s) that are interested in the CART_ITEM_ADDED event could then update the CartStore and tell it to refetch the cart from the server. Once done the store would fire an event saying no more than "OK. I've changed" and then it would be the responsibility of each view that is subscribing to CartStore to refetch the information they need from the CartStore.

On to debugging:

In my dispatchers, when running debug mode, i always print what events are being dispatched. So in your handleViewAction you could do a console.log('[DISPATCH]', action); which would give you a clear overview of which events are being dispatched and in what order.

You could do the same thing when your stores emit a change event. Log it and you'll know whats happened.

It's very hard for me to tell you the exact problem without more to go on but normally it's very easy to confuse and mix the constants for your dispatcher callback & actioncreators. Maybe you are listening for the wrong events in the wrong places somewhere?

Also i see you're doing something like

FeedStore.addFeedListener(this._onChange, 'feed-area.js');

Is there any reason why you don't use a generic addEventListener?

All you should tell the store is "Hey! Run this function whenever something has happened, ok?" by doing FeedStore.addEventListener(this._onChange);

This became a longer answer than i expected, and i hope it helps, if not then please feel free to ask!

Upvotes: 2

Related Questions