This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

React Flux: Stores

6:03 React lesson by

Stores are where the real work in our application is done. Dispatchers broadcast Actions to all Stores, and the Stores registered to listen for those Actions will perform any logic needed to update our Views. In this lesson we will establish our first Store and register the Actions we wish to respond to.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

Stores are where the real work in our application is done. Dispatchers broadcast Actions to all Stores, and the Stores registered to listen for those Actions will perform any logic needed to update our Views. In this lesson we will establish our first Store and register the Actions we wish to respond to.

Avatar
Jeff

I have 2 questions here:

  1. It appears that you are using the the same items in the catalog to represent items in the cart. Then you're just adding new properties to those items (inCart and qty). It seems as if this would ordinarily have used a CartItem that perhaps referenced the CatalogItem, but maintained the qty by itself. Am I missing something that makes my concern invalid?

  2. You're again managing the cart by array index. If this were an async app, would it be possible to have, say 2 items in your cart. Then you click remove on first item, and increase on the second. If done quickly enough, would the increase event be sent with index 1, instead of it's new index (0)? I guess I'm at a loss as to why the cart is an array instead of a hash with item ids as keys.

In reply to egghead.io
Avatar
Joseph
  1. It is not that your concern invalid it just involves a different approach. In our example our dataset is so small and so closely resembles exactly what we need to build up a list of cart items that it works really well and keeps the purpose of the tutorial intact.

  2. I'd have to write a test that runs your particular scenario to be certain, but our dispatcher should prevent the race condition you are describing. Array vs a reference to the catalog item id? The end result is the same and the lesson content is focused on Flux Architecture rather than unrelated complexities.

In reply to Jeff
Avatar
Rafael

Hello! I'm trying to understand Flux and how everything works and these videos are being super helpful!

Now, on the Store file, it's still a bit strange/confusing to me that we emit change by running AppStore.emitChange() right after our switch statement instead of emitting the change after each function (ie.: after addItem or removeItem) as a callback or something).

Just for testing, I set a timeout on the 'addItem' function to delay its response/logic and the change is emitted 'before' the 'addItem' task has been completed, which breaks the App cause the Cart listens to the 'eventChange' and updates its own state while the latest data isn't there yet.

Should I be concerned about this happening with more complex apps or am I missing something here?

Tks!

Avatar
Matthew

What do you do when you need to use a store in more than one component? Would you require() the store in a parent/controller view then pass it through the props to children?

I've started a Stackoverflow question: http://stackoverflow.com/questions/36380193/how-to-use-store-in-multiple-componenets/36380301#36380301

Hey, guys. In this video, we are going to create our application store. This is where most of the Logic in our application is going to live. I'm going to create a new file here in our store's directory called appstore.js.

In this video, I'm actually going to be pasting in a handful of items just for the sake of brevity. Here, we are going to be bringing in app dispatcher and app constants, which we created in previous videos. Again, we're going to be bringing in an object that assigned from the React library. We're also bringing in EventEmitter from Node.

We are going to create a value here called change event. It's going to be equal to this key of change. This is what we're going to broadcast every single time something changes in our application. We're also going to have a value here for catalog. It's going to be an array.

We're just going to be building that up, so I've dropped in some code here that just cycles through and pushes these objects into it. This is going to represent our catalog for our shopping cart, so we've got all these widgets. They have title, summary, description, and a cost. We're going to have cart items. This will be an array of those items that we actually have in our cart.

Again, I'm going to be pasting in a handful of methods here. The first one is "remove item" which is going to remove an item from our cart items. It's going to find the item in our cart items and set its in-cart value to false. Then it's going to splice our cart items at that index.

Increase item is going to do exactly what it sounds like it does. It finds the item in our cart items and increases its quantity value by one.

Decrease item -- let me scroll this into view -- is going to take an index just like increase item. It's going to see if the current quantity is greater than one, and if it is, it's going to go ahead and reduce that by one. Otherwise, it's going to go ahead and call our remove item method.

Add item -- let me get this into view here -- is going to see if our item is in the cart. If it's not it's going to add a quantity of one in cart, set to true, and it's going to push that item into our cart. Otherwise, we're going to cycle through and find that item. This is if it's actually in our cart, and then we'll just call our increase item method for that item.

Finally, we've got cart totals which is basically just going to end up cycling through our cart and returning an object that has a quantity key and a total key, each one, so we have our total quantity and our total cost there.

Now, we're going to go ahead and building our actual app store object that we're going to export from this code here. We are going to start with our app store. We're going to use the assign method to extend EventEmitter that prototype.

Here's our object. The first thing we're going to need is a way to emit a change. This will be a function. All we're going to do is say this.emit. That's the EventEmitter's emit method. We're just going to say change event.

After that we're going to need a way to add a ChangeListener. It's going to be a function. This one is going to take in our callback. We're just going to say this.on change event execute our callback.

The next one is going to be remove ChangeListener. This is going to use this.removeListener, exact same signature which change event and callback.

Then we're going to need a way to access the majority of our private method. Get cart is going to be a function. It's going to return cart items. Get catalog, also a function. It's going to return our catalog. We're also going to need to get our cart totals. Here, we're just going to return our cart totals function.

This next bit doesn't actually require a key, however, if we have multiple stores or if we have a store that needs to wait on another store, it's important that we have a way to reference this. I'm giving it a key of dispatcher index.

I'm going to call dispatcher.register. It's going to take in a function. That function takes in our payload. Here, I'm actually going to paste in some more code for the sake of brevity, and I'll walk you through that.

From our payload, I've grabbed this action value, and I've assigned it to a variable call to action. We're switching on what the action's action type is in order to determine which private method we should call. If it's add item, we call our private add item and we pass in the item. If it's remove item, we call remove item and we're passing in the index and so on for increase item and decrease item.

At the end of that, we go ahead and emit our change. Then finally we return true so that we can actually resolve to the dispatcher so it can move onto the next action.

I'm going to save this guy. We're going to need to export this, exports app store.

Cool, we now have our app store, and we are ready to move on to creating all the components that are going to tie everything together.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?