In Flux our Components are referred to as Views, but they are the same familiar Components associated with any React development. In Flux, however, we have the benefit of the architecture to keep us from having to pass down through a long chain of children Components any functionality that may be embedded in our Stores. In this Lesson we will wire up all of our Components in record time utilizing the architecture we've already established.
[00:00] Now that we have our store built, we can begin building our components. I don't know if you know this about me, but I have tremendous design abilities. This is a wire frame that I put together, and what we've got up here is our catalog component. We've got the title of our item, the cost of our item, and this add to cart component.
[00:20] In our cart here, we've got the ability to remove an item, increase and decrease the quantity, and see our totals. Based on that, we can go ahead and get started building our components.
[00:32] In a previous video, we took a look at how app actions is going to work. What I'm going to do here is I'm going to copy this old guy right here and create a new component. This is going to be our app add to cart component.
[00:47] I'm going to paste that right there, and let's see. We're going to change this to add to cart, do the same on our export. Rather than passing in a string, it's going to be this prop's item, and let's see. This is going to be a button, and it's in our HTML. It's going to be add to cart.
[01:12] This is just part of the beauty of Flux. We didn't. Have to inherit anything, we just created our quick little component. The only thing it actually inherited is the item that is going to get past him, otherwise, everything came from app actions. We are going to copy this guy once again. We're going to create a new component here.
[01:31] This is going to be our App.RemoveFrom part component, paste this guy in here. Our component is going to be called "remove from cart." Here, rather than add item, we're going to remove item. In this case, rather than the item itself, we are going to be passing on the index, and we'll just go ahead and update this to an X.
[01:57] Again, we're just going to copy this exact same code here. Create our app IncreaseItem.js, paste in again. This will be increase item, and let's see.
[02:18] Here, we're going to say increase, and here, we'll just do a little plus symbol. One more time, copy this guy, create our App.Decrease item. Decrease, decrease, a little minus symbol there, exporting decrease item.
[02:54] We just created all four of those components in record time. We didn't have to worry about any functionality being passed down to it. Again, this is part of the beauty of the Flux application architecture. The next component we are going to create is our catalog component.
[03:07] That's going to be App-Catalog.js. If you take a look at our wire frame, this is going to be this section up here. We're going to have a the item here, and we're going to have this table with each of our items and our add to cart component. To build that up, we're actually going to go ahead and drop in our requirements, which are react, our app store, and our add to cart component.
[03:32] Then, you create a function here called "get catalog." This is going to return our initial state. It's not going to return an object. If you have a key of items, the value of those is going to be AppStore.GetCatalog. Let's go ahead and build up our component here, called "catalog."
[03:51] When we're all done, we're going to expert that, of course. Our get initial state, we're simply returning our get catalog method from above. In our return, we're going to paste this in. We are returning a table, we've got a little bootstrap class on the table, and a table hover.
[04:12] Then, we've got the subject called items, which we are going to create right now. Our items equals This.State.Items.Map picks in each item. We're going to return a table row, that's TR, and we're going to have one, two, three table dialogs. Let's go to get those in there.
[04:38] Our first one is going to have our Item.Title. Our second one is going to have our Item.Class. We'll put a little dollar sign right at the beginning of that. Our third one is going to be our, "add to cart," component and it's key of item is going to be equal to the item. We go ahead and save that guy.
[05:03] Now, in our app component, let's say, we don't need this handler any longer. What we do need, rather than app actions, is our catalog component. Then, what we're going to return, something that looks like our wire frame. Let's wrap everything in a div, drop an H1 here. It says, "Let's shop." Below that, we're going to drop our catalog component.
[05:33] Now, if we jump over to our application, reload this guy, you can see we've got all of our widgets in our catalog. If we want to bring up our console, we can see that in fact each time we click on this, we are sending our object to your dispatcher.
[05:51] Now, we are getting a message here that we need to have a unique key, here on our catalog items right here, we're going to set a key equal to Item.ID. That should resolve that issue. There we go. We can see that each item is carrying over the item, then, we can see we've got our cost and our title, it's actually passing the item.
[06:16] Now, we need to create our cart, which is very similar to our catalog, go ahead and copy that. Create a new component here called "AppPart.js." Paste this guy in there. In our cart, we're going to need react. We're also going to need the App Store, but we are not going to need add to cart. We're going to need remove from cart.
[06:37] We're going to need are increase and decrease component. Rather than get catalog, we're going to need our cart items. This will return get cart. In our initial state, rather than get catalog, we're going to be calling cart items.
[06:56] Unlike our catalog component, this component needs to actually be aware of changes in our application. What we're going to do is we're going to say, component will mount, and right now, we're going to use our AppStore.Addchange listener. We're going to call it This.Unchange.
[07:21] We're going to go ahead and create that method right now. Here, what we're going to do is set our state to cart items. What we're really saying is any time something changes, we're going to get our updated state of our cart items and make it the state of our cart component.
[07:31] Here in our render method, we've already got items, so we can reuse some of this. We're going to need to calculate our totals here. I'm going to say var total equals zero, get us started. While we're living through this, we're going to go ahead and calculate our subtotal and use that to increment our total.
[07:50] Now here in our return, for the sake of brevity, I'm going to paste this in and we'll take a quick look at it. Again, we are returning a table row. We've got in the first column, we've got our remove from cart, and we're testing in our index, which we need to get in our mapping method right there.
[08:06] Then we've got our title, our quantity, and then we've got our increase and decrease components, and then finally we've got our subtotal. Now here, in the return of our component, again, I'm going to paste this in and take a quick look at it. We're returning a table with a little bootstrap. We've got a header, and our table header, we've got an empty one here which is for our remove component.
[08:28] We've got our item, which will be the title or quantity. We've got another one here for increase and decrease, and then, we've got our subtotal.
[08:35] We drop our items into the table body, and then in the footer, we've got a table dialog here with a call span of four and a classing of text right just to get that word total all the way over to the right, and then, we output our total.
[08:48] Go ahead and save that. We'll jump over here to our app, and drop in an H1 here in the cart. Then, we're going to need our cart component, and I'll try this guy out. Let's reload our app in the browser. Oh, cart items is not defined. That should be asked right there.
[09:09] One more time, cool. We have our cart, we can add items to it, I can have a few of these guys. We'll increase the values here, and we will remove a couple of those items. This is widget A. Using our current app store, we can go ahead and add that a bunch of times and we're looking good.
[09:26] One thing I noticed as I have this variable called catalog still in our cart component, I'm going to go ahead and update that to export cart. That's a minor tweak there, and everything seems to be working as expected.
in app-store.js I had to make the following change:
var AppStore = assign({}, EventEmitter.prototype, {
emitChange:function(){
this.emit(CHANGE_EVENT)
},
to avoid React key warnings in app-catalog.js :
var Catalog =
React.createClass({
getInitialState: function(){
console.log(getCatalog());
return getCatalog();
},
render: function(){
var items = this.state.items.map(function(item){
return <tr key={item.id}><td>{item.title}</td><td>${item.cost}</td><td><AddToCart item={item} /></td></tr>
});
return (
<table className="table table-hover">
{items}
</table>
)
}
});
Yep, App.js example file was not updated.
/** @jsx React.DOM */
var React = require('react');
var Catalog = require('../components/app-catalog.js');
var Cart = require('../components/app-cart');
var APP =
React.createClass({
render: function () {
return (
<div>
<h1>Lets shop</h1>
<Catalog />
<h1>Cart</h1>
<Cart />
</div>
)
}
});
module.exports = APP;
I've made the change suggested by others here (thanks!) but still come unstuck.
Tracing as best I can, when I click on the Add To Cart button, I can see the handleClick function fire, the VIEW_ACTION being dispatched from the app-dispatcher with an ADD_ITEM actionType, _addPromise being called in the dispatch method of the base dispatcher, but Promise.all(_promises).then(_clearPromises); never seems to resolve and fire the "then" clause.
Not of the events seem to be emitted.
Would be nice if the files provided worked/up to date :( even after following advice above still getting:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of Catalog. See http://fb.me/react-warning-keys for more information.
I'm getting the following error: "module "react/lib/merge" not found"
I'm guessing this stems from the boilerplate dispatcher code. Did I have to do anything to install the module that I missed?
Try checking out the flux website and getting the copy of the dispatcher from there under 'Creating a Dispatcher'. https://facebook.github.io/flux/docs/todo-list.html. It requires installation of the es6-promise module and object-assign, but I've found so far object-assign is the easiest way to get around the merge requirement since merge has been deprecated since this video was released.
I was getting the same issue. This worked for me. npm install merge var merge = require('merge');
If you're getting this error - "module "react/lib/merge" try doing this. npm install merge var merge = require('merge');
If you're getting this error - "module "react/lib/merge" try doing this. npm install merge var merge = require('merge');
Joe, one of the nice process related things about this course are the analysis & design wireframes, not only the interface mock-up but also the one showing what still needs to be implemented. Are you using any particular application to create these diagrams? Thanks for a great, up-to-date and very clear video series!
how does 'this.setState()' inside '_onChange' work? _onChange is passed to eventEmmiter. So won't 'this' point to a wrong object when '_onChange' is called by eventEmmiter? or am i missing something here?
What I miss is a discussion of how to handle errors in the flux architecture. Maybe an idea for a new movie?