What do you want to learn?
Skip to main content
Building a Full-Stack App with React and Express
by Daniel Stern
Build an isomorphic web application that implements React, Express, Mongoose, and much more.
Start CourseBookmarkAdd to Channel
Table of contents
Course Introduction / About the Author
Why React and Express?
Well if you've clicked this tutorial series and have watched this far, you're probably already pretty interested in learning how to make a React and Express app. Nonetheless, I'm going to explain exactly why the best reasons to do so are. Who knows, maybe you'll need to explain this to your boss or other commanding officer. So why React and Express? Let's start with looking at React. React provides fast, client side views. I don't know if you've made a React app or used the React app, but these apps are really, really fast. They use special optimizations on the DOM, or document object model, to make the display update more quickly than with any other library. Even on a super powerful machine like mine, the difference is between the speed, the proceed speed, and a React admin angular app, are actually huge. So if you build your app with React you're setting yourself up to build the fastest app possible. That's really cool. Now where does Express fit in? So Express provides a powerful backend. A backend is, you can sort of look at as an API, it has some, you know, maybe some logics and authentication stuff, some secrets. But also it's responsible for fetching data from our repository and sharing it with your frontend view. As would be managed by React. You can choose to use any backend, many are extremely effective. However, Express is extremely good for a number of reasons. Not only is it one of the fastest and most expressive backend routing tools in any language, but React and Express together are super cool. React and Express work together to make apps that are isomorphic. An isomorphic app is basically the same on the backend or the frontend. Though that isn't quite accurate. The technical definition of an isomorphic app is one that if you load it by jumping to the browser, it will load up as a static app in other words, as fast as possible with all the data being expressed as HTML. And then a single page app will Bootstrap onto it, in the case or React, and sort of animate it. So you get it from the server, basically looking right, but having no guts. Like, some sort of shell. So using this together you can create even faster website drops. We're actually going to learn all about that and build an isomorphic app in this tutorial. So I hope you stick with us to the later modules.
Introduction to React, Part 1 - The Performant Library
Introduction to React, Part 1 - The Virtual DOM
What Is Express?
Why Express Makes Sense for React Applications
App Preview, Part I - The Relationship Between Tools
Hello ladies and gentleman, in this final video of the introductory series we're going to have an overview of our finished app. A finished isomorphic react Express app, full stat. But first let's review how the components have of our app interrelate. MongoDB is the long term storage, it stores all our data, our user names, our list items, whatever you want. Express and Node leave the data from MongoDB and delivers the content to our frontend, which is running React. On some occasions Express will serve the generator React HTML and then React will Bootstrap to it after the fact.
App Preview, Part II - A Look at the Finished App
Scaffolding the App
Creating the Initial Scaffold
Hello ladies and gentleman, and welcome to the next module of this course. In this video we're going to be setting up the scaffolding for our app. So while we won't be seeing any of the apps real functionality in this video, we'll go a long way to building an app that is both scalable and extendable. Let's start by opening up our terminal window. We'll init a new NPM package and a bower package, so let's do NPM init and just press Enter through all the options. And let's do bower init, by the way if you don't have bower, please install bower with NPM install bower-g first. Then once you have bower installed, type bower init. And you'll get the same list of options. Just press Enter. Now if we have a look at our app, it's created a bower.json and a package.json for us. Next we need to include a git ignore to prevent these JSON files from being, well to prevent the NPM packages from being committed to our repository. So in our terminal let's just type touch.gitignore. And you can see it's been created, so let's go to this file. And we'll add node modules and bower components. Next let's add the main directories of our app. Our React stuff is mostly going to go in a folder called app, which we'll create now. Conversely our server stuff will go inside a folder called server, which we will now create. In our app directory, let's create the main entry point of the app. So we'll create a new file and we'll save the file as index.html. In a later tutorial, we'll be converting this to an EJS file, but now is not the time for that yet. In our index let's just add a simple hello world to make sure our index is working. Next inside our server directory we need the main backend file of our app. We won't be writing too much in it in this module, but we'll still want it loosely set up to do one or two things. So in your server directory, create a new file and call it main.js. So to get our app working we need to install a few modules. So open up your terminal and type NPM install ---save. Using the save flag we'll save the package to your NPM file. And for now we're just going to grab Express. So with Express loaded up, let's scaffold a very basic main.js to serve our app. We'll say Express is equal to and we're require Express. Then we'll create a variable called app and make that to a new instance of Express. We'll have the app listen for a request on our main route, which is just the forward slash. Inside this function, whatever I passed to res.send or sometimes res.render, will result in what is displayed. So we'll say res.render and we'll pass a string to our new file. And finally let's have our app listen to port 7777, so it can respond to requests. That's looking pretty good. Let's try running in our terminal window, server/main.js, to see if works. And let's open up our browser and now if we navigate to local hosts 7777, we get an error. It says when using res.render it can't find the module HTML. This can be solved by making our index file an EJS file, so let's go ahead and do that. Let's go to our index and we'll just rename that index.ejs. And we'll go to our main js and let's change this to index.ejs. Now let's run our server again. And now we see Hello, world! So we've got in a basic scaffold set up. In the next video we'll add some more automation and functionality to our app.
Setting up the Gulp File
Transpiling our First JSX Script
Bundling the Application with Browserify
Creating a React Component
Creating a React Front-End
Displaying a List of Items with React
Currently our app does not do anything. The first thing we're going to want to do is display a list of grocery items in our application. To begin, let's go to main.jsx in our app folder. Now let's create a simple array of items that have a name and a purchase property. I'm just going to paste one in for the interest of time. So I've created an array called initial and it has four items in it, Ice cream, waffles, etc. You can put whatever items you want. Notice that some have a purchased flag, which indicates, in our app, whether the user has purchased the item yet or not. Now we'll set the initial items as a property to grocery item list. So in our JSX here at the bottom, we'll say items = and then we'll put single curly brackets. Whatever is inside single curly brackets gets interpolated by React. React is very strict, so if you make any kind of mistake with the syntax, it will tell you. Let's put initial inside those curly brackets. Now our list of items is a property of our app. Now let's navigate to our grocery item list. So after this H1, let's put a div tag. Inside this div tag, we'll put a pair of curly braces. This indicates that this is going to be interpolated by React. So what we're going to do is we're literally going to make the contents of these curly braces a map of our items. In JSX code you can put maps right inside the HTMLish part, which is confusing, but let's have a look. So now we have a map block inside of our HTML. Whatever is returned by this function will actually become the HTML or JSX that composes our website. It's a very new way of doing things. So let's return in round brackets and then curly brackets we'll just put item.name. That's all looking good, let's verify that it worked. Open up your terminal and type Gulp serve. Hmm looks like we're getting an error. Let's have a look. Unexpected token dot at line 11. What does that mean? Ahh, here on line 11, React requires that everything is inside some kind of HTML element here we've just orphaned this item.name without any tag at all. That's no good. So let's put that inside a div tag. That's looking better, let's run Gulp serve again. And there you have it; our map has turned our list of items into a list of div tags. In the next video we're going to move this item into its own file.
Compositing React Classes
Here we have our list of items; however, this list is baked right into the same file as our main app. So in this video we're going to put it in a different file. Let's go to our text editor. First, let's take this line, div item.name and we're just going to cut it out, it doesn't belong in this file anymore. Now let's create a new file in the components folder called groceryitem.jsx. First we'll require React at the top of this file. Since we already have the code in our first file, let's just copy and paste it. It's similar to the last file; we're going to make the module.exports of this file equal to react.createclass. And as we know, all classes must have a render function. Now let's return in round brackets and let's paste in our line of code from grocery item list. Hmm well that works, but there is no item in this scope, is there? No, since we're going to be assigning this via props, we should change this to this.props.item.name. Can you guess what the next step is? That's right, we're going to compose this component into grocery item list. So let's go back to grocery item list and let's require our new file with the require keyword. Now inside our return function let's compose our element that we just created. Let's create a grocery item div element. And as the property item we'll pass item. One gotcha with React is that if we're going to compose elements inside a map like this, we're going to need to have a key property. So let's give it a key and just make that equal to the item, word item plus the number of the index. If we did everything correctly, that should work. Let's go to our browser and check it out. Everything's looking okay so far. Hmm, one problem though, we can't really tell the difference between the items which are bought and the items which have not been bought. Let's add a simple class to denote what this is.
Conditionally Applying Classes
So here is our list of items, but there's one small problem, we can't really tell which items have been purchased and which items haven't been purchased. Let's use React to add a conditional class to handle this. Let's navigate back to our text editor let's navigate over to groceryitem.jsx. First, let's wrap out text inside the div tag with an H4 tag, to make it bigger. Now we'll give the H4 a class name property. Since the word class is reserved, you can't use the word class in your JSX. You have to use class name instead. Class name is just like class in almost every way, that's a tricky little gotcha with React. So we'll make that equal and we'll put a statement with single curly brackets. So we'll take the variable, this, which refers to the component itself, .props.item.purchased. And you'll remember one of our items had the purchase property set to true. And we're going to put a ternary statement in here. If statements don't work in JSX, but ternary statements work just fine. So we'll say, is it true? If so give it a strike through class. If not, give it no class. That looks very good, just one more thing now. Let's create a new file in app called styles.css. And we'll add a strike through class; I'm just going to paste this in. Since this is just CSS and we don't want to spend any time discussing CSS. Feel free to pause and copy that in if you're coding along from home. Finally let's go to our index.ejs and add a reference to this styles file. I'll just copy that in there. And now let's make one quick update to our Gulp file. Here we're going to want to make a new task copy that copies our styles.css to our temp directory. And we'll say gulp.src, app/*.css.pipe and we'll just pipe that to gulp.dest. And we'll pass the temp directory. Now let's make bundle dependent on copy. That looks good, let's restart gulp serve and see if that works. Very nice, as you can see we now have a conditionally applied strike through class on our candy item. We're still using our browserify Gulp workflow to manage these CSS, so our app is still as scalable as before.
Implementing a Flux Dispatcher
We're now going to learn how to add new items to our list. As you may know, React uses an architecture called Flex wherein all changes flow up to the top then back down. If you find this confusing, don't worry, because we're going to be implementing Flex ourselves right now. Let's navigate to our text editor. First we're going to implement a simple dispatcher. Let's create a new file called dispatcher.js. Now React and Facebook have their own dispatcher, which is open-source and free to use. But I've always found dispatchers a little bit confusing, so I'd prefer that we implement one ourselves so we understand what's going on. First we're going to need the NPM module GUID, so open up your terminal and let's install that real quick. Let's say NPM install save guid. This is a tool for generating random strings. And let's require that. Now a dispatcher registers listeners and then sends events to those listeners at the appropriate time. So we have to have an array or an object to do that. We can use either, but in this case let's use an object. Now we're going to make module.exports equal to an object. And we'll give that object two methods. You guessed it; let's call this methods register and dispatch. Two sides to the same coin. Register will be passed a callback represented by CB. So in register, let's create a unique ID for our CB. Then we'll put that on the listeners object where the key is the ID. And we'll return the ID. Now a fully formed dispatcher has more than just register and dispatch and the ID is used in these additional functions. However, for this simple app, we only need register and dispatch so we won't get into the more complex element of dispatchers. So for our dispatch function we're going to want to have a console info, because this is a very useful place to have a little debugging information. That will come in handy later. Then we'll loop through all the listeners in dispatch and for each listener call that listener and pass it the payload. Alright, we've now implemented a fully functional dispatcher. We'll be using it in the coming videos.
Adding New Grocery Items to the List
In the last video we prepared our dispatcher. In this video we're going to create a component that can use the dispatcher. So let's create a new file in our components folder and call it grocerylistadditem.jsx. And let's require React at the top of this file. And once again, module.exports will be equal to react.createclass. Let's give it a render function and we'll have that return in round brackets. So let's put a div and we'll give that a class name of grocery add item. Now inside we'll put a form. And let's have this form return just an input and a button. Now let's go to grocery item list and compose this item into our list. Right at the end, after the list of props. First we'll require it by having an item reference at the top. I'll just copy and edit this. And let's include that in a tag at the bottom. No need for any props. If that all worked properly, this should display in our app, let's have a look. And here is our list, as you can see we have an add item field on the bottom. It does not do anything yet. In the next videos we're going to hook this up through the Flux system.
Using Forms in React Applications
We've now implemented an add item field, but it doesn't do anything, it's just a dummy placeholder. In this video let's hook this up to our dispatcher. So let's go to our text editor. And let's go to grocery list add item. So to make this input live, we have to give it a value that's equal to something. So we'll make the value equal to this.state.input. And since no such value is defined, we have to set it in get initial state, another React create class built in function. And this will return an object with an empty input property. That's looking good. Now as it is, the input's going to forever stay blank, because we're not telling it anywhere to change the value of this.state.input. Unlike Angular, it doesn't work both ways. This binding is only a read binding. To set a write binding we have to add the on change property. And we'll make a function name, handle input name. Now we'll define that method and we'll get the argument E, who's target will always be the input. We'll call this .setstate, you must never change the state directly by manipulating the state object. You must call this.setstate or React will not update appropriate. And in set state we'll just make the input equal to whatever the value is of the bar. Not bad, but it still doesn't do anything, let's hook it up to the dispatcher. So let's add an on submit to this form. And we'll make up a function name, this.additem. Now let's define that function. And we'll just put a console.log statement in there for now. And we want to call e.preventdefault on this submission event. So let's restart Gulp and have a look at how our app works. Here I have my developer tools open, open them with Ctrl + Shift + I on PC or Command option I on the Mac. Now if I type in a new item and try to add it, I get a message on the right. So our form on submit is working. In the next video we're going to make a helper to help us hook this up to the main dispatcher.
Implementing an Action Helper
In this video we're going to create an action helper, so that the creating of our item makes it all the way to our dispatcher. Let's go to the editor. Let's create a new file and let's create a new folder called for it called actions. And we'll call it grocery item action creator. That's a mouthful. And save that. So this is going to be a connector between all our files and our dispatcher. We're going to need a reference the dispatcher, so let's require it. And it's a level up, so we need to those two extra dots. And then a similar fashion to before, let's make module.exports an object. And we'll give it an add method, which takes an item. And inside this, this will be very simple, we'll just say dispatcher.dispatch. And pass it an object. The object will have a payload property, which is the item. However, in Flux actions also are better to have types; a type is just a string. It's any string defined by you, but ideally it gives the dispatcher and stores lots of information about what's happening. I'm going to call my type grocery item: add. This is a convention which I'll be using regularly where for actions related to grocery items it will begin with grocery-item. So stores that are dealing with grocery items can filter out the events that matter to them from the events that are irrelevant. That all looks good, let's go back to grocery list add item and require the action creator. And we'll say var action and we'll make the equal to the path of our item creator, it's a long one. Now inside add item let's erase this console log and instead say, action.add. And we'll pass it a simple object where the name is this.state.input. And after this is done, we should reset the input to empty, so the user can enter another item if they want. Alright, we should see a different console log now. Let's restart Gulp and have a look at our app. Alright, so now if I try to add a new item to the list, here's our console info statement from before. We know this is getting all the way to the dispatcher, but our app isn't updating yet. Hmm, before we can finish up we need to implement a store, one of React Fluxes most characteristic components.
Creating a Flux Store
So far we're created a great dispatcher and hooked it up to our add item component. But the messages that the dispatcher is sending are going nowhere, they're going unheard. We need to create a store to listen to these messages. So let's go back to our text editor. Let's create a new folder in the app directory called stores. And we'll create a new file called grocery item store.jsx. Whenever I work inside this file, I get the irresistible urge to go to the grocery store, I'm not sure why. First, let's require the dispatcher in our grocery item store file. I'll just copy that in from the file where we've already written it. So we're going to do this a bit differently, we're going to first define a class called grocery item store. Don't worry; we're just going to use the function keyword. No ES6 in this tutorial series, unfortunately. And we'll make the module.exports a new instance of this store. This makes sense, because a grocery item store, you can literally think of it as some sort of building where you're keeping all your grocery items. Whenever any component of your app, be it your list or your add time, wants to interact, it has to go to the store. And the store decides what the canonical true state of that data is. The more you work with React, the more you realize how great stores are. And stores have just one rule, only the store may change the data inside the store. Other components may request that the store change something by dispatching an event, but it is only the store that can change things. Therefore, when something changes in the store it's much easier to figure out what happened. So the store itself holds an array of grocery items. You can kind of look at stores as big fat fancy arrays. And it also is going to hold an array of listeners, so let's define an array of that. The first thing you should be able to do with the grocery item store is get all the grocery items. So let's add a function for that. And we'll just return the items. Now let's add something so that something can register a change listener. We'll call it on change and it will just push the listeners to our array of listeners. Next let's add a function to trigger all the listeners, so when you call this function everything that has been listening to grocery item store is informed that things are changed and receives a new copy of the items. I'm just going to paste this on in. So let's register with the dispatcher. We'll call dispatcher.register. Whenever the dispatcher dispatches anything, this will be called. We're only interested in this file with types that have grocery item at the beginning. So let's create a switch statement for that. So if the thing before the call is equal to grocery item, go into this switch statement. So if the second part of that is the word add, and we'll define a new function here add grocery item and we'll pass it the payload. And we'll call break. So let's write that function now. Let's create a function, add grocery item, and this will be very simple; we'll just say grocery items.push, the new item. And we'll trigger the listeners. Finally let's return at the end of this function an API of public functions. So we'll return an object and that object will have just get items and on change. These are the only two parts of the item store that are exposed to a public interface. Everything else is meant to be secret. The idea is that other components shouldn't be able to tamper with what's going on inside the store. We've now implemented the store. In the next video we're going to hook this store up to all our other features.
Completion of Add Item Functionality
Well it has taken us along time. Implementing a React application is anything but simple, but we're finally at the point where we'll be able to add new items to our list. And it will be very much worth it. First, let's go to main.jsx. Let's take the dummy list of contacts out of main.jsx and put them into our grocery items store. This is where they'll stay until we set up a backend in the following modules. Next, back in main.jsx let's require the grocery items store. And we'll make initial equal to groceryitemstore.getitems. Let's just give that a small g. Now let's put this render clause inside its own function, we'll just call that render. And we'll call that now whenever groceryitemstore.onchanged is called, we also want to render. And let's update this, since this should be stores, not components. And give it another shot in the terminal. Hmm, we're getting an error, callback is not defined. Let's have a look. Hmm, let's go to our dispatcher.js this should be cb, not callback. And we'll give it another shot. Our app appears. If we attempt to add a new item, hmm another error, change listeners is not defined. Hmm, makes sense. Let's go to our store. And there is no change listeners, only listeners. Did you catch that? That was a test, I was testing you. And while we're at it, there is no grocery items either, that should be items. Let's give it another shot. Alright, so here we are back at our app. And if I try to add a new item, it works. Now we have an active living app. Notice how quickly the response time is when I add a new item. That's React. You're probably found the workflow that we used fairly confusing, we needed a store, a dispatcher, an action helper, all to do this. But the results are well worth it. Not only is our app now faster and more reliable than most other apps out there, but turning it into an isomorphic app later on is going to be a breeze. Congratulations on getting this far.
Completing the Front End
Deleting Items from the List
Well it certainly did take us a long time to implement the functionality to add new items to our grocery list. That's because we had to set up a store, a dispatcher, an actions helper, etc. However, with all this scaffolding in place, it will be very easy for us to edit items and delete them. Let's get started with deleting items. Let's go to our text editor and let's go to groceryitem.jsx. First let's wrap our H4 in another div tag. Then after that tag, let's put a form. We'll give the class name for the form three columns and on submit we'll call the this.delete method, which we'll write momentarily. I'll just paste that in. Note that n times just makes an x. Alright, so let's make a delete method on this item, above render we'll define delete and we'll say e.preventdefault will prevent the page from refreshing. Next let's require our action creator in this file. I'll just paste it for when we've required our action creator before. And we'll call action.delete in this one. And the delete action doesn't exist yet, so let's create one. Let's go to our action creator and we'll just copy this and paste this. Change the word add to delete. That was a bit simpler. Next let's go to the grocery items store. We need to register for this listener as well. So let's add another case here in our switch statement. And we'll call delete grocery item, which does not exist, so we'll have to create it now. So in delete grocery item, we'll find the index of the item. So now we have the index of the item where the name is the same as the items we're trying to delete. And we'll just splice it out of existence. And don't forget to trigger listeners. Alright, I'm cautiously optimistic that this might work, let's restart Gulp. Hmm, and it looks like we have a teensy error, find index does not exist. Well it looks like old Daniel's gotten ahead of himself and written ES6 without realizing it. Ahh, let's turn this into ES5. Let's go back to our ID and we'll just remove this sugar and turn this into a filter loop. Alright, so now our find index has been desugared into normal ES5. In the original version of this app I used a lot of ES6, since it's so easy to use with the workflow. Well let's restart Gulp serve. Alright, so our apps open and let's give it a shot. Let's press the big X button. And the thing disappears; let's try adding a new one. And there you go. So we successfully implemented deleting items and adding items. Did you notice how it took us about half an hour to implement adding items, but only about five minutes to implement deleting items? This is how a React app goes. The learning curve is a bit high, but the rewards are well worth it. In the next video we're going to be unbuying and buying items and you'll find it's really just as easy.
Only one element remains to be completed in our React frontend, the ability to buy and unbuy items. If you're feeling like I do, you're extremely excited to see this app fully in action. So let's get started. This will be very similar to the last video. First let's add a form to buy or unbuy the item. So let's just make a copy of this form and copy it above. Change the top one from on submit from this.delete to this.togglepurchased. And let's add a conditional class to this button. If it's purchased, don't give it any class. If it's not purchased, give it a primary class. And let's change the text depending on whether or not it has been bought yet. That HTML looks good, but we need a toggle purchased function. First, we prevent default so the page does not reload. Then we'll have a conditional, if the item is purchased, unpurchase it. We'll call action.unbuy. If you're thinking there is no action unbuy, very good, we haven't written it yet, we'll write it momentarily. And so we'll say, otherwise call yes, you guessed it, action.buy. So that should be fully functional as far as the HTML goes. Now let's go to the action creator. We'll define two more methods, buy and unbuy. You can probably imagine how they're going to look. Very nice. Now let's go to the grocery item store and we'll create two new cases for buy and unbuy. For buy we'll call this function that we're about to create called set grocery item bought. And the first argument will be the event payload. And the second argument is going to be whether we want to set it bought or not. In the buy case that's true. And in the unbuy case it's false. Now let's write the function. So we'll locate the item in the main array with a filter. So that filter says, return me the first element where the name is the same as the name of the item being passed. And we'll change the item purchased to whatever the variable being passed is. And of course we'll trigger the listeners. Alright that's looking very good. Let's restart Gulp and see if it works. Alright here's our app and it is looking very complete. We can buy and unbuy items, delete them, and add a new one. That's awesome, we've basically implemented a full React frontend, this is already a real cool app. One problem is, restart the page and it's all gone. In the next module we're going to implement an Express backend so that these things persist, possibly forever.
Adding Styles to the App
Well our app is fully functional, but it's a little bit ugly, it has no CSS and whoever heard of a website without any CSS? In this short video we're going to make our app presentable. We'll be staring at it for a long time over the next few modules, so this is a good thing. First let's pop open our terminal window. We want to install the library skeleton, which is a lightweight way of adding styles to our app. Consider it like a lightweight Bootstrap. So let's say bower install save skeleton. Alright, now let's go to our index.ejs and let's include our skeleton before our custom styles. I'm just going to paste this in since hey this is CSS, you should be familiar with this by now. So here we have our normalized CSS and our skeleton.css and I've also sneakily snuck a title in there, in that same copy and paste. You can feel free to add a title to your app if you wish, it can be different than this title. Now let's wrap everything in a div with the class container. Now let's go to our styles.css. So I've prepared a few styles just to make this app look a little tighter. I'm just going to paste them in since they have nothing to do with JSX. If you'd like to copy them, I'll give you a moment to pause and copy the styles down. As you can see, we're just adding text decoration, a bit of margins, some body, etc. So with that updated, let's have a look at how our app looks. Hmm, not quite right, let's make a few more changes. So let's go to our groceryitem.jsx and we'll add some additional classes. In the interest of time, I'm just going to copy and paste in the changes, these are only CSS changes. As you can see, several six columns, rows have been added, this is just to make our app look okay. And let's restart Gulp and have a look. Alright, our app is looking great. Just one thing missing and that's a style on the add item field, so let's fix that up right now. Alright and our app is looking premo. We have a fully functional React frontend that's well styled and works great. In the next videos we'll be adding a backend to this and finally making it isomorphic.
Implementing an Express Back End
Creating an Items Route
Implementing a Route in Express
We now have our items.js containing our list of sample items. Next let's update our main.js in server to include this file. So all we need to say is require and we'll pass the name of our new items file. And since this is a function, we'll put another pair of round brackets after it. And we're going to pass it the app variable, which is an Express app. So now our app has the API/items route. If we restart Gulp and give it a try. Here I am at the webpage, if I go to /API/items, you can see here in JSON format is my list of items. So now we've implemented a backend and that's a bit more persistent than our one we had in the previous module. Changes to this will persist beyond when the browser is refreshed. So we need to get this data into this frontend view. Luckily that shouldn't be too hard.
Adding Body-Parser Express Middleware
Currently we're working on our Express application. Now to properly interpret post requests and other more complex kinds of requests. We need to install some middleware into Express. So we're going to need the library body parser let's open up our terminal and install it. So I'll say NPM install with the save flag. And we'll install body parser. And that's that. So let's go back to our file and we'll say var parser = require body parser. And we'll say app.use. Now body parser has a few different functions. We're going to want to use parser.json. This allows our Express application to process JSON requests. We'll just copy and paste this and we'll also want to use parser.url encoded. And this will allow us to handle post requests with Express. And we'll just pass it an arguments object. And say extended false, which will cover us for compatibility reasons. Now that we're set up with body parser we should be able to interact with our backend from the frontend of our application.
Creating a REST Helper
At this point it's been a while since we've made any changes to our React frontend. In this video, though, we're going to update it so that it actually collects this data from the backend, instead of having its own hard coded list of items. So we're going to want to create a new folder in our application folder. And we'll call that helpers. For this application, we are only going to need one kind of helper. We'll call it a rest helper, which will simplify making rest requests and keep AJAX code out of our app logic. And here we have resthelper.js. So to make our AJAX requests, we're going to use jQuery, however, we're not going to add a script tag to index.html as maybe the familiar way of installing jQuery. Instead, we're going to use NPM, which we'll find is a much more elegant solution. So let's open up our terminal and we'll install with a save, jQuery the popular frontend library. So that looks like it's installed, let's go back to our file and we'll require jQuery in our helper. So we'll say var$ and we'll make that equal to require jQuery. And we'll make the exports of this module equal to an object. For now we're only going to add one method to this object, a method called get, which takes a URL. We'll be using an asynchronous syntax, so let's return a new promise. This is built in to the ECMAScript 5 ECMAScript 6 spec and should be available in the browser you're using. Now a promise takes a function with two arguments, success and error. And inside we'll call $.ajax. And we'll pass that a configuration object. It will have four arguments. The URL argument will be equal to our URL, which is passed there in the function get. We'll specify a data type and make it equal to the string to JSON. And we'll give it a success method and an error method, which will be the same as the methods of the same name being passed into this function. And that's looking good.
Implemeting GET Requests
We will now implement the rest helper we've prepared. The actual rest calls will be done from groceryitemsstore.jsx, so let's open up that file. And first off we're going to want to require our new rest helper, so let's do that right at the top. So here at the top we're going to get our items from our backend. So we'll say, helper.get and we'll pass in the URL from before, API/items. Then we'll chain the then method to that. And this will be called asynchronously after the data arrives. And once we do get the data, we'll make the list of items equal to that data. And then we'll trigger the listeners, which reminds any components listening to the store to update. Lastly, let's remove these dummy items and make the items variable equal to a simple empty array. And it looks like we've made one small error, this should be helpers/resthelper. Alright, so it looks like our app is functional. It looks basically the same, however, if you refresh it, you'll notice there is a very brief flash of no content. That's because the app really is loading the data up from the backend. It may be difficult to see on my screen, but if you're coding along at home, you should definitely be able to see the brief flash of no items. If we try to add an item, it works, but if we refresh, it still does not persist. Luckily we're going to be able to persist our items very soon using the scaffolding we've just created.
Modifying data with POST requests
Very shortly we'll be implementing a MongoDB which will offer us a permanent database solution. However, for now, let's add the ability to add contacts to our list of items, which is currently being managed by Node and Express. So as you may know, usually if a get request gives the requester a list of items, making a post request the same URL, will often modify that list. And that's the kind of rest API we will be implementing. So first, let's go to our rest helper file. So we want to give it a post helper. So let's just start by copying and pasting this get helper. And we'll make a few slight modifications to it. Change its name to post and give it a second argument called data. Post requests often include payloads of data that tell the server what sort of new data should be added to the collection. And to our dollar sign AJAX call, let's add another configuration to the object and call it data. And we'll make that equal to the argument data. Alright, so we have a post helper, however we need to add something in the backend to actually handle this post request. You'll recall that we made a route for this very thing. So let's go to routes/items.js. So to our .get we can chain a .post, which has the same signature. Now if I make a post request to this URL, this logic that we're typing now will trigger instead of the above. Instead of sending the list of items, we're going to want to modify the list of items. So we'll get the payload, which is equal to request.body. And we'll just say items.pushitem. Alright, so that should persist our items indefinitely, but we actually still have to make the post request. So let's go to the grocery items store. So here we are in grocery items store you'll recall the add grocery item function, which just pushes the item to the list of items. Now we're going to want to keep this like it is. In our React app we're going to want to update optimistically. So we like the instantaneous response of our list being updated the instant that our item is pushed to the list. Sure, you know, there could be a problem, maybe the request of the server won't work. In that case, we can recover gracefully and show an error afterwards. For the purposes of this tutorial, we won't cover the error handling, but we'll still make sure we have a perfectly functional app. So after we've pushed the item, let's make a request to our items endpoint to tell it a new item has been added. We'll make a post request by calling helper.post. And we'll pass in the URL, same as the URL before. So that's API/items, but we're posting to it. And the second argument, our data, will be equal to the item. To add error handling, we could add a then handler to the post, which would make sure that the code returned is a 200, which means that everything's okay. We know that it will work, because we haven't written in any sort of validation to our backend. So if this is all written correctly, our app should now work. Let's save this, restart Gulp, and see how our app is working. And we seem to have made one small error. Inside rest helper, let's change the data type from JSON to post it the post function. And for the post function let's change the word data type to type. Alright, that's looking good. Let's restart Gulp and see if our application is working. Alright, so here we are at our application. If I try to add a new item, the item appears. If I refresh the page, our item persists indefinitely. So now we've created a pretty functional app as long as we don't restart our Express server, our items will persist. If we do restart our server, like for example by restarting our computer, our items will be gone. So we still need a permanent solution. You'll notice that deleting items does not persist nor does buying them and unbuying them. Since we're going to be implementing MongoDB next, it's not necessary for us to implement the buying and buying logic inside of Express. We'll be implementing that shortly with MongoDB.
Installing and Running MongoDB
Alright, in the previous video we installed and started Mongo. Please make sure that you have Mongo running at this point if you're coding along with us, because we need MongoDB running or the application won't quite work. So let's navigate back to our text editor. Let's start by creating a new file in the server directory and we'll call it database.js. Our database file is where we're going to do most of our interacting with Mongo. However, we're not actually going to use the MongoDB API, instead we're going to use a middleware called Mongoose. Mongoose is basically a Node module, which makes it very easy to do RESTful things with MongoDB. So let's open up our terminal window and we'll install with a save, Mongoose. And we'll just let that do its thing. And it looks like Mongoose was installed successfully. Let's go back to our test editor and we'll say var mongoose and we'll require that module. Now we'll say, mongoose.connect. Mongoose only needs to connect to a database once, and it will persist the session allow us to communicate with that into the future. So we'll pass the URL, this can be any URL. If it doesn't exist, MongoDB will conveniently create it for us. I'll just call mine something along the lines of local host/grocery. And the second argument is a function. And this function is called whenever a connection occurs. So we'll just say connected. Finally, in server/main.js let's require our database file so that it runs. We'll say requiredatabase.js. No need to assign it to a variable. Alright, so let's see what happens when we run Gulp. As you can see, it says connected there right after live reload. So our MongoDB is successfully being connected via Mongoose. Next we'll add files to MongoDB.
Creating a Schema
Implementing the Item Model
Next we'll convert our default values into values for our database. Let's navigate to routes/items.js. Now let's cut this list of items. We'll put this item in the callback that we wrote in database.js. So here after connected, we'll define these items, then we'll do a for loop through them. We need our reference to the grocery item model, so we'll say grocery item = require and pass it the path to our grocery item model. So with Mongoose, to create a new item you actually invoke the model with the new keyword, so we'll say new grocery item. And we'll pass it the item which you'll notice matches the schema we defined. And then to that we will chain the .save method, which will persist this permanently in our database. Alright, that looks good. The final thing is we're going to want to return the data from the database when we go to our route. So let's go to routes/items. So we'll require our grocery item model, just like we did in the previous file. I'll just copy and paste that, since we have it on hand. And we'll just add an extra .. to the this, so that goes to the correct route. Now in get what we'll do is we'll wrap this res.send in a groceryitem.find call. So if we call groceryitem.find and not pass it any object, it will simply return a list of all the grocery items, this is precisely what we want. So we'll pass this a callback function where doc is the array of items. And then we'll pass that to res.send. Similarly for post, instead of the code we have here, we'll create a new grocery item with new grocery item and pass it item. And we'll call groceryitem.save. And it takes a callback and after the callback we'll call res.status300, which means okay, .send. And it looks like we made a little error, let's rename our grocery item model to groceryitem, this is a model for just a single item. Let's restart Gulp and give it a shot. Looks like we have a little error in server/routes/items, items is not defined. And that's because in this context the items is actually called doc, which stands for document. So we'll update that, now let's give it another shot by restarting Gulp. Alright, so we're getting some interesting results. As you can see we're seeing our items, but every time that we've restarted the server, the items get added to the database again. As you can see, ice cream appears three times. If I restart Gulp ice cream now appears four times. This is probably not what we want, so let's go back to database.js quickly. So after it's connected we're going to actually drop the database, so any data that was created before we restarted the server, will be dropped. I know this isn't really very persistent because the data's not really going to persist once we restart the server again. But the functionality is there and for development purposes, you are pretty much going to want to create a new seed every time. So we'll just call Mongoose.connection.db and drop it. If you'd prefer your data to be a bit more persistent during development, you can omit this line, but I warn you the list will get pretty long. So let's restart Gulp alright and our app is working. If we try to add a new item to the app, everything works as expected. So now we've implemented MongoDB and have given our data the opportunity to persist for a long time. Also this makes our app more scalable. Because let's say our grocery app becomes very popular and millions of people are using it, since we've already begun implementing a database solution, we're not going to run into the performance problems we'd get if we just ran with say, Express operating on the file system. So this is good. You'll notice that buying and unbuying items, as well as deleting them, still does not work. In the next video we're going to quickly implement that.
Adding Patch and Delete to Express and Mongoose
In this video we'll be implementing the functionality to edit and delete items as they exist in our database. Let's navigate to routes/items. Now we'll add an additional route for app.route. Now we'll add an additional route for items/idvariable. Let's have a look at how that looks. So with this ID with the colon before it, means that whatever is passed to the URL after items will be a variable in this context called ID. So if I were to go to API/items/Daniel the variable ID in the function I'm about to write, would be equal to Daniel. So we're going to want to be able to delete items at this route, so we'll add a .delete. This will be invoked if someone makes a request to this route using the delete method. And we'll pass it a function. And here we'll say groceryitem.find. And this delete function should take two arguments, req and res. So we'll find our ID in req.parameters, so the configuration we pass will say ID is equal to request.parameters.id. And then we'll just chain .remove to that. So Mongoose will find any items with the matching ID and remove them from the list. Next let's chain a patch handler to this route, so whenever this route is called with the patch method the following code will run. Now we'll find a reference that the item we want to update with groceryitem.findOne and inside the configuration object we'll just say _id = request.body._id. And the second argument to find one is the callback. So the body of the request is going to be the actual sort of patch object kind of the new object that's going to replace the old one. So we'll loop through all the keys in the patch object and update the doc that we just found with them. And then we'll call doc.save. And we can also send a 200 status, which means okay. With delete and patch implemented in our app, all we have to do is hook into these in our frontend and our app will be fully complete.
Updating Editing and Updating Items on the Front End
Conclusion (Back End)
Alright, here we are at our completed app so far. And the app really is nearly complete. Here we have a list of items, we can add new items to the list, delete items, and update items. If we have a look at our code base, we can see that we have our app broken up basically into two main folders. Inside the app folder we have all of our frontend code, our React, our jQuery, but we're also implementing this code using the require syntax, which is typically something we do on the backend. Here in our server directory, we're managing our MongoDB and our Express with different files. We've modularized our Express to some of our Express is here in main.js. While some of the Express is here in routes/items.js. All in all, the app is almost complete. All that remains is to make it isomorphic.
Making the App Isomorphic
Updating the EJS Template for React
Adding Isomorphic Functionality to Express using React and Babel
Big Picture Overview
In this video we'll take a big picture overview of our finished application, starting with the backend web application. So we had a scaffold made up of bower, NPM, and Node to collect the files. And Gulp and browserify to actually do the file transformation and the serving. On our backend we're running Express, when Express receives a request it responds with frontend code, often isomorphic. To facilitate this, MongoDB persists our data to a database indefinitely. This let's use construct a serious and scalable app. Finally to make interacting with Mongo easier, we've implemented Mongoose on our backend, which makes it easier to interact with this kind of database. Now all that has the net effect of serving our page and getting our content together. But what displays our content? On the frontend React is displaying our content with an emphasis on speed and user experience. React Bootstraps itself automatically to the isomorphic code created by the backend. After being Bootstrapped, it becomes active and interactive code. We're just using good old jQuery to do our AJAX requests. We could use a more sophisticated library like Angular, but that's not necessary at this time. And finally, we use browserify to manage our frontend dependencies.
Ideas for Taking the App Further
In this video we'll discuss how you can further your education regarding React and Express. First, we wrote a bunch of React code, but we haven't tested it. React has its own test framework called Jest. Learning about Jest was beyond the scope of this series of modules, but I encourage you to take up learning some Jest if you want to increase your React knowledge. On a similar vein, our Express code was also untested. Express code can be most easily tested with a library called super test. So if you wish you can implement super test to reinforce your Express code with some tests. Next, you'll notice in our app, we'll anyone could log on and add grocery items and delete them, without really authenticating themselves as the owner of those items. Passport allows our users to authenticate themselves, essentially giving each one access to their own list. Implementing Passport is fairly challenging, but doing so can really take this app to the next level. Finally, we did construct a fairly trivial app, it only has a list of items, it doesn't say do anything interactive like add the prices of all the items together and maybe tell us which the most expensive one is. But of course, this is something that a computer can easily do. So to augment your app and add prices, would be adding a lot of interesting functionality.
Continuing your Education
Well it's been an outstanding series of videos. If you've gotten this far, that means you've probably watched them all. I would like to personally congratulate you for watching to the end of these video series. This has been one of the most challenging apps that I've ever made. If you've followed along all the way to end, it shows me that you're determined and absolutely focused on mastering frontend and backend web development code. I believe that if you simply continue on the path that you're on, you are guaranteed to succeed and to accomplish whatever personal or professional goals you have regarding developing with React, Express, or any library you set your mind to. From everyone here at Pluralsight, I'm Daniel Stern, have a good day.
Released17 Aug 2015