- Read Tutorial
- Watch Guide Video
So in user.js we need to introduce a new type, so go into types.js
and up at user let's say export constant authenticate user is equal to authenticate user okay.
types.js
// USER export const SET_USER_PURCHASES = 'SET_USER_PURCHASES'; export const SET_PURCHASE_DETAIL = 'SET_PURCHASE_DETAIL'; export const AUTHNETICATE_USER = 'AUTHENTICATE_USER';
So we're going to have to go to our user again, so let's go to user.js
in our actions, and let's import authentication, so let's import authenticate user from types and again we're not hooking this up to the backend because this is the frontend course. But what I'm going to show you is exactly what we would do if we were to retrieve this from a database.
So let's say export function signIn right, we pass in the credentials like an email and a password and then we pass it to the server right, and then we get back a response. And then what we're going to do with that response is basically dispatch an action or return an action that's called authenticate user and then with that, we pass in the user, okay, and typically with like a JWT token or we use something else for authentication like http only cookies, okay.
So let's say user and let's pass in the user object which we get back from this server right, we're going to call this payload though, but just remember it's the user okay. And we can even just say that it's user, or we can just do this okay, the user's going to have... we'll model it that way just in case we add it to a service, so it will be like that and we'll say user and add another object okay, so payload has a user in it.
User is going to have an ID right, user is also going to have a name of course, and then the user is going to have an address right, and then the user will have a few other things. The point is we only need the name in there and an address at this point. So I mean this is where card products is going to exist so ideally we should refactor our code to have the cart products exist on the user, but we're not going to do that at least not now.
user.js
import { SET_USER_PURCHASES, SET_PURCHASE_DETAIL, SET_CART_PRODUCTS, ADD_CART_PRODUCT, AUTHENTICATE_USER } './types'; export function signIn({email, password}) { return ({ type: AUTHENTICATE_USER, payload: { user: { _id: 0, name: 'Max Nelson', address: '1234 I live here', cartProducts: [] } } }) }
So we have the name and the address what we need to do now is dispatch this action right so we need to go to our reducer and create a case for authenticate users. So let's go in to what is it? User.js
in shop research so user reducer right, in user reducer let's import authenticate user. So import authenticate user from ../action/types, excellent. Next thing we want to do is put a user on the top of this initial state an empty object okay and then put a comma so it doesn't break. Next step is to go to the switch right here and say case authenticate user in here what we're going to do is we're going to take it out of the payload, okay we're going to take it out of the action.
So we're going to say constant user is equal to action.payload and we're going to extract that from the payload that we're getting back from the server in this case that we've hardcoded right here as payload with user in it. We're then going to take this user and we're going to return our state and then we're going to take the user and override it with this object. Excellent, so we've implemented the action in the reducer, the next step is to see if this is in our state when we sign in. And the place we want to call this is in our signin.js
as soon as we submit our thing okay.
So let's go to our application and let me show you. Okay, I'm talking about login right here, login is going to dispatch this action. So if I console log the fields right, if I inspect the element here and then login when I select console you'll see that we are printing our information here, let's see, sign in, login.
Alright, it says because the form is not connected.
So we have an error with our form, let's fix this really quick okay. Let's go to signInForm.js
and we're doing something in here, we've got handleSubmit onSubmit is equal to handleSubmit, and then we have login, we this login and it's type is submit. So it should be submitting our form but it's not okay, so let's take a look at why. Let's go to our Chrome here, let's type some data in here and hit login. Okay, so it's submitting but for some reason it's saying that it's not.
So what we want to do is refresh the page, let's hit logout, then hit refresh and login and it doesn't work. Okay, so forms submission cancel because the form is not connected. So likely what's happening here is... I know exactly what's happening here. We're pushing it directly to there when we call it, we don't want to do that. Let's get rid of this and let's get rid of the onClick entirely in our signInForm.js
.
What we need to be doing is leaving that the way it is, and then moving history okay. So make sure you take history, copy it because we're using it in here still, copy history go into signin.js
and in here we need to import it so that we can basically say... well we don't even need this, we can use this.props
because it's part of our router it's a direct route okay because in bootstrap.js
our sign in is a direct route right, it's a direct route thats part of our route.
So what we can do is we can say this.props.history.push/account
and we want to move this to onSubmit not component did mount. Alright, so what's going to happen is when we click it it's going to print our fields and then we're going to be pushed to account. So let's go to Chrome, let's logout, let's hit login and you see it says e-mail testtest@gmail.com and that the password is password? That's exactly what we want.
So now what we need to do is call this.props.signin okay. Remember in user.js
we just exported this function called signIn that takes an email and a password okay, and we're going to console log that in here now. You could also write this as fields or anything else right, it's just an object, you could say object and then say console log object.password right.
I'm going to do it this way so you understand better what information is coming in through here. And then what we do is we pass this in with the information on the server and then we'd sign the user in, get the user back after we're authenticated and send it to our application to store locally. So let's go back to signin.js
and let's get rid of this console log fields right. So we're not going to see the console log in here anymore but once we hook up the action right now, once we say this.props.signIn and pass in the fields we will see it.
But before this works we need to go to our index.js
in our actions folder and actually import it from users, so let's say signIn and then let's head down here and let's make sure we are exporting it out of our index.js so signIn.
index.js
import { fetchUserPurchases, setPurchaseDetail, fetchCartProducts, addCartProduct, signIn } from './user';
export {
setHeaderLinks,
setNavbarLinks,
changeNavbarActive,
fetchUserPurchases,
setPurchaseDetail,
fetchCartProduts,
addCartProduct,
signIn
Okay let's close out of index.js and let's try this out. So I'm saying this.props assigning fields. Logout, login you see it prints email and password, that's exactly what we want.
It's printing email and password, not because we console logged it in here, but because we console logged it in user.js
in signin alright. So let's get rid of that console log and before you save the file... we'll just save it because a lot of you probably already have saved the file, and head over to the application log out and let's sign in one more time and then now let's look at our redux dev tools.
You'll see now that we have a user that contains the user and this user has an ID a name and address and cart products.
Obviously we haven't wired is 100% the way we would on a backend, we haven't wired this exactly how we want to. But I've shown you plenty of information on how to do that right, through out building this, it should give you a really solid idea of how this works right. So you should be able to fix little inconsistency and ideally we don't want to fix the inconsistencies back and what we want to do is build a backend that we can hook this frontend up to.
Now when you're building out an application the ideal thing to do is to start with the backend because this has already been somewhat of a challenge to do this instead of just hooking it up to the backend. We wouldn't have had to perform half the logic in this application if we just had a backend to do it and I have a backend built, but I wanted to take this approach to give you another unique perspective.
I thought this might help you understand things better because in the property management app we cloned a server in that way, so this might help you understand the models a bit better, and what's going on on the backend which will make things easier when you go through backend courses if you do.
Anyway we're containing the user object now, what we need to do is extract the name and address so that when we are in... let's see, let's flip some of these around, and add them, just because it looks cool, then what we want to do is hit proceed to checkout right. Then what we want to see in payment information is the correct name and address in here okay.
So let's go ahead and let's head over to the payment information application and extract this information and put it in here instead of hard coding Jordan and 1234. All right let's head over to paymentForm.js
okay, let's then go and import connect from react redux. So let's go to the top here and let's say import in brackets connect and we'll pull it out of react redux.
import React, { Component } from 'react'; import { reduxForm, Field } from 'redux-form'; import { connect } from 'react-redux';
Okay, so that is some function that's being exported out of react redux and it's not a default component right. This is being exported just as export just to help you understand how this works. Remember how we made orderSummary? This component we exported as a default component right and then in info help we exported under line title as just the function, we just exported it so we could have multiple things in here.
So same thing with react redux, in react redux there's multiple functions right, there's multiple things that are going on in there. So we're able to import connect as one function from there, it's not a default piece of behavior in react redux, it's a piece of react redux. Okay, let's go down here and let's utilize it. Let's say PaymentForm is equal to connect and we'll pass in mapStateToProps, we'll then pass in not actions but we'll bind it to payment form.
Now what we'll do is we'll type out function mapStateToProps and pass in state. Alright, we're then going to go and take out the name and the address out of the state.user.user
. Now keep in mind the user right here is the reducer this user is the user we just stored.
paymentForm.js
function mapStateToProps(state){ const { name, address } = state.user.user; }
So let me go to userReducer.js
and show you what I mean okay. So initial state this is user right, this is the user reducer and then in here we have a user okay. Alright let's close out of userReducer, let's go to paymentForm.js
and let's actually use these okay. So first we have to return them so let's say return name and address and let's go in here where it says Jordan Hudgens and let's put braces and say this.props.name
and then where the address is we'll say in braces this.props.address okay.
So they should all be wired up and working now, let's go to Chrome and see what this looks like. Okay, nothing but that's just because we haven't logged in, so let's hit login, it stores the data right, we go to shop, we go to checkout, we checkout, we proceed to checkout, and we use this address right and it says Max 1234 I live here.
So you get the idea of this entire application and now the real test is, what are we going to... like are we going to hook it up to a backend right? Are we going to get the backend for this application? And that's what the Python course is for okay, so this is the frontend part of the course, if you're in the react Python course then this is the frontend part okay.
If you're interested in building a backend and actually having it work with this, having it process payments with stripe and all that. What you're going to have to do is go through the python course I'm about to build after I finish this course okay. So that's it for this course, that's how you build the frontend for the e-commerce application alright. So let's go ahead and commit our code.
Terminal
git status git add . git commit -m "added sign in functionality"
All right and I'll go ahead and push this up to GitHub, so I'm going to do that just while I'm recording because why not? So (github.com)[github.com] and what I'm going to do is I'm going to... and feel free to follow along and create your own repo, you probably already know how to do that at this point. But what I'm going to do is I'm going to hit start a project
and I'm going to put it on bottega-code-school
I'm going to call it ecomm... I already have a repo called ecomm? Let's just call it... did I put this on github already? I'm going to say git remote, okay so there is no remote so thats fine. Okay, I'm going to call this... let's call this front-end-gummy-code
okay. Description is front end implementation for Gummy Code Ecommerce site
.
So let's hit create repository
and I'm going to go ahead and I'm just going to copy these two right here right, push an existing repo from the command line
and I'm going to paste that into our terminal here okay, and that's just going to handle everything for me. So if you want to do that, go ahead and do that.
Right, well if you're going to take the Python course I'll see you in the Python course, if not I'll see you in the next react course.