In this lesson we'll create our initial components using the architecture we've built so far.
[00:00] In this lesson, we're going to take a look at adding our components or our views to our application using the Flux Application Architecture we've already set up. Here is a look at our application as it's going to be when we're completed. We've got this catalog component here that houses each of these catalog items.
[00:16] They have an addToCart, which adds a single item to the cart. We've got this cart summary up here, which keeps track of the total quantity of items as well as the total costs. If I add this guy and this guy, we've got nine items at $16. We can jump to our cart, and we can remove items. We can decrease until they're removed. We can also increase the quantity.
[00:39] We can also jump to an individual view of our single catalog item, and we can do the same from here. There's a lot of reactive stuff going on here. The state is tracked in various places.
[00:52] We are obviously quite a ways away from that, but what we're going to do is go ahead and build up our catalog component and our cart component. We're going to try to get both of those on the same page, keeping track of the state of our application.
[01:03] To get us started, we're going to go on and create a handful of files, the first one being our app catalog. We're also going to app-catalogItem.js. Catalog will be our container, catalogItem will be the individual items. We're going to do the same thing for carts. We're going to have app-cart.js. We're going to have app-cart-item.js.
[01:30] Then finally, a shared component for all these guys is going to be app-cart-button.js. That'll essentially be for our addToCart, removeFromCart, increase, and decrease. We're going to start here with the catalog. In our catalog component, we're going to need React. We're going to need AppStore, and we're also going to need this catalogItem component, which we'll create in just a moment.
[01:52] We're going to create a function here called getCatalog. This is going to get our component's initial states, which is going to return an object with a key of items. That value is going to be equal to AppStore.getCatalog. We'll go ahead and set up our ES6 class component here. We're going to call that catalog.
[02:16] Now, we're going to need a constructor here to get our state set up. We're going to call super in order to get the context of this. We're going to say this.state equals getCatalog. Then in our render, we're going to say let items equal this.state.items.map. We're going to map through these guys. Each one will be an item.
[02:40] We're simply going to return our catalogItem component. That's going to get a unique key. We'll use the item.id, and then we're actually going to pass in our item as a prop. Then the JSX, that will actually return, just be a div with a class name of row from bootstrap, and then our items. We'll go ahead and export that by default, and we'll start creating our catalogItem.
[03:10] For our catalogItem, we're going to need React. We're going to need AppActions, and we're going to need a component that we're going to create in a moment called cartButton. Now in this one, we're going to be exporting a default function, which takes in props. This is going to be our first stateless component.
[03:25] Here, we're going to return some JSX, which I'm going to paste in for the sake of brevity. Walk that really quick, we've got a div with some responsive bootstrap. We've got an H4 with our props.item.title. We've got a placeholder image here. We've got our summary in a paragraph tag, and we've got our costs in a paragraph tag.
[03:44] Now, the one other thing we need here is our cartButton component. That's going to take in a handler prop, which is going to be equal to AppActions.addItem since this is our catalog component. We'll bind that to null and pass in our props.item. Let's go ahead and create our App cartButton.
[04:05] Of course, we're going to import React. Again, we're going to export by default a function. That takes in our props. Again, we're going to return some JSX here. That's going to be a button with some bootstrap styling. It's going to have an on-click that triggers the handler that we just passed in. It's also going to take in this prop of text, which we'll add right here in our usage.
[04:28] That'll be addToCart. We'll save that. We're actually going to jump over here to our app component so that we can start getting a look at this guy. We're going to import our catalog. We're going to return that, going to wrap it in a div with a class of container. Since it does start with a row, it's going to output our catalog.
[04:53] It does look like we're getting an error here. It's a lot of code to type up without actually trying it out. We've got an issue here in our catalogItem where I had our text variable wrapped inside our handler variable. Save that. Try it one more time. This.state.items.map is not a function, so that's going to be in our catalog.
[05:18] This should have been a function call. We'll try that one more time. We've got our catalog on the page. We've got our addToCart button. We should see that in the Dev Console, and we do. Add this item, that item. We can expand these and see that the item being passed in is the correct item.
[05:37] I'll now move on to creating our cart. For our cart component, we're going to need React. We're going to need our AppStore. We're also going to need our AppcartItem, which we'll create in a moment. Now, to get our state here, I'm to create a function called cart items, which we'll simply return items AppStore.getCart, which we created in a store in a previous video.
[06:00] Go ahead and set up our cart ES6 component. Set up our constructor, call super. Set our state to equal cartItems. Now since this component is our first component that really needs to be aware of changes as they happen, we're going to set this up a little bit differently than we did our catalog component.
[06:24] With this one, we're going to have an unchanged handler. We're going to go ahead and bind that here now, so this_unchange.bindthis. We're going to have a component. We'll mount phase. We're going to AppStore.addChangeListener.
[06:40] We're just going to pass enter this.unchangedMethod. Then on our component, we'll unmount. We're gong to remove that ChangeListener. Finally, we'll create our unchanged method, which simply sets our state whenever there was a change using the cartItems function.
[06:58] In our Render method, again, I'm going to paste in some code for the sake of brevity. We'll take a quick look at it. We've got this variable of total, and then we're mapping through the items in our state. We're adding up a subtotal per item as well as our complete total, which will drop at the end of the table. We're returning this AppcartItem, which will be the item in our cart.
[07:20] If we look at our completed application, that'll be each of these rows. There's our AppcartItem, and then we've got some general HTML here in our JSX. We call it, cart. We've got a table. We drop our items in the table body there. Then at the very end, we've got a really wide table dialogue to get the value of total all the way over to the right. Then, in the last table dialogue, we have our actual totals.
[07:45] We are going to go ahead and export this guy by default and create our AppcartItem. Here, we're going to need React. We're going to need our cartButton component, and we're going to need Actions. I'm going to export this as a stateless component. It takes in its props, and it's going to return some JSX, which I'll drop in right here. We'll take a quick look at it.
[08:09] It's a table row. First table dialogue has a cartButton that has a text of x for our removeItem action, and that's receiving the props.item. We drop in the title and the quantity. We've got a button group here that has two cart buttons. One for decrease, which has a text of minus, and then an increase, which has a text of plus. We'll save that. Jump back over here to our app.
[08:37] We'll drop our cart here, which we'll import into our component. We'll try that guy out. Minor typo there. Cool. Now, we have our cart. If we go ahead and get rid of this guy, we can see we'll add this item to the cart. Add this item to the cart, we can see we've got our total.
[08:59] We can increase our quantity, decrease it to zero, which will remove it, or we can just remove it directly. We can add a bunch of these guys, and everything seems to be working as expected.
React 0.14.x can render a function as a component. It is treated like the render
method on a Component
https://egghead.io/lessons/react-building-stateless-function-components-new-in-react-0-14
Why are the action methods called with bind? AppActions.addItem.bind(null, props.item) instead of AppActions.addItem(props.item)
This is a common JS, not React specific, practice that allows us to pass the function to the child component along with arguments, but letting the child component execute the function when appropriate. AppActions.addItem(props.item) would execute immediately, and in this app, perpetually.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
in app-store.js , _findCart(item) function should return the cartItem :
const _findCartItem = (item) => { return _cartItems.find(cartItem => cartItem.id === item.id); };
this will help during add item. by not returning, it will create new table record instead of just incrementing the item.qty
I have some issue Object.assign ? how to resolve this
I have some issue Object.assign not a function ? how to resolve this
I also have an issue with Object.assign where it throws and error into console "Uncaught TypeError: undefined is not a function" and doesn't render app
hi, I just curious why sometimes you use es6 class to define the component, and sometimes you just using export default for the component?
i.e: export default (props) => { return ( <div className="col-xs-6 col-sm-4 col-md-3"> <p>{props.item.cost}</p> </div> ) }
why? plz advise.