Now, that we have completed updating the server-side.
It's time to move on to the react client.
For your convenience, I have provided you with the GitHub repository,
that contains the final version of the client that is able to communicate with
our REST API server and then render the various views for our client.
So, I have taken the reapplication that we developed in
the second course of the specialization and then modified it.
We will take a brief tour through the code a little bit later.
Now, you will clone the Git repository to your computer,
and then start-up your client and then see it communicating with our server set.
Let's see the details next.
To get started with this exercise,
at your terminal or command window,
go to your convenient location and then at the prompt type git clone
https://github.com/jmuppala/conFusion-React.git, and then let
the React application be cloned to your computer.
Once the cloning is complete,
move to the conFusion-React folder
that has just been created when you cloned this Git repository.
Then, you will immediately notice that there are a bunch of files already there.
Now, at the prompt, type yarn install,
in order to install all the node modules on
which this React application is dependent upon.
So, once the node modules are all installed,
then we can start up our yarn start to compile and serve up our React application.
Once everything is in,
make sure that your MongoDB server is up and
running and also your REST API server is also up and running.
Otherwise, client will not work.
So, now that you have installed your client on your computer,
add the prompt type yarn start
and your application will be recompile and served up in a short while.
Once your application is successfully compiled,
go into the browser and you will see that
your React application gets started up and is visible on the screen here.
You will notice immediately that your application is
able to fetch the data from the server and then render
the various parts of your application just like what you
did at the end of your React course.
When you go to the About folder,
you will also see that the About page also renders the information.
As such earlier in the menu,
you see the items in the menu being displayed just like we saw with the application.
Now, in addition, I have added in
one more page to the single-page application called My Favorites,
which you cannot navigate to,
because no user is logged into their system.
So, you see that I don't have any user logged in to the system.
So, that's why there is no point in indicating my favorites because you don't know
which user as favorites should be shown here and the contact page as usual.
Now, let's log in.
To log in to our application,
we'll click on the login button and then you would see that the login dialog pops up.
Then let me login as one of the registered users,
which we registered as part of this course earlier.
So, once you log in,
you will immediately notice that to the right corner,
you see the login button has now turned into
logout and the user's name is indicated here.
So, whoever is logged in is indicated here.
You can also in principle replace this with the image of the user.
Now, for that you need to do more modifications to
both the client and the server in order to support the image display here.
But at the moment, I'm just showing you,
how we can easily display the user information here.
So, this required minor modification to the head of component,
where I will be able to retrieve the username.
So, once the user logs in,
then if you now click on My Favorites you would
notice that there is nothing in My Favorites for the user.
Obviously because the user has not yet chosen any favorites.
So, let's now go to the menu.
Then, in the menu,
let me select one item and then we will add this dish to our favorites.
So, going down below here,
you'll see the heart symbol there,
click on that, and you'll see that this would be added into the favorites.
The fact that this has been added into the favorites,
is indicated by the change in the icon here from a unfilled heart to a filled heart.
Now, if you go to any other dish,
you would notice that this has an unfilled heart
which means that this is not yet among our favorites.
So, let me add in one more item to
my favorites and then let's add a third item to my favorites also.
So, now, you will see that if I now go to my favorites,
you will see a set of My Favorites being displayed here.
So, you saw that I just added these three dishes
to my favorites and so these are being displayed here.
So, this is tracked by using
that favorites endpoint on
the server-side whichever implemented as part of your last assignment.
So, if you have done that assignment correctly,
then this part should work as expected.
Now, we can also modify My Favorite.
So, let me go ahead and delete one of the items from My Favorites.
So, when I click on that button you'll notice immediately that,
that item is deleted from My Favorites and immediately disappears and
my favorites gets updated and you see the resulting value being shown here.
So, notice that the My Favorites will be displayed only
for users that are logged in to the system.
So, you immediately notice a set of changes that have been
done to the client in order to support
some of these additional features that you see here.
You also saw the login and logout feature being supported here.
So, when I click on the logout button,
you immediately notice that the user gets logged out and
the username disappears from there and
so the button also is turned into the login button.
Now, so, with this you notice how my client has been
updated to make use of the new REST API server,
in order to support the favorites being saved on the server-side and
then automatically being reflected into My Client application as shown here.
Now, that you have seen the modified React application in action,
it's time to pay a visit to the source code to see how
exactly is it implemented and what are the changes
that we have made corresponding to the Redux application at the end of the Redux course.
Now, the two major changes that you will notice,
is the support for favorites and also the authentication support,
the user login and logout support.
Now, how are these implemented?
We will start our journey in the Redux part of our application.
So, going into the Redux part,
let's visit the action types.
In action types, you will see now that we have
three new action types related to their favorites.
So, you would see favorites loading,
favorites failed, and add favorites,
which as you would expect to be there.
Then, also six different action types related to their login and logout process.
Now, so you can see login request, login success,
login failure, logout request,
logout success and failure.
So, we'll see how these action types are actually used in our action create.
So, going into the action creators,
so this is where you will see the support for the favorites here.
So, we will first examine the support for favorites and then after that we will
examine the support for the authentication support.
So, in here, you will see that we have new methods down below
here called as favoritesLoading, favoritesFailed, and addFavorites.
Now, from your previous experiences
dishesLoading and dishesFailed and addDishes and so on.
So, these things are very familiar to you,
so that it's exactly the same kind of setup for the code here.
In addition, you will see another method here called fetchFavorites,
which is again as I said a Redux tank,
which is implemented here,
where we will use the fetch to access the server to fetch the favorites.
So, these are the methods that you will see here and then also you will see
deleteFavorite here and also a Redux tank for postFavorite here.
So, in the postFavorite as you would expect,
you would be posting the favorite to the server here.
So, here notice how we are using authorization.
Being set up in our authorization header so,
this is something that I would draw your attention to at this moment,
we'll come back to this again when we look at the user authentication and authorization.
So, we are setting up the authorization header like this using fetch here.
So, for fetch, we are posting an item into the fetch
here and then you will notice that the structure of how the fetch is done is given here.
Now whenever you post a favorite or delete a favorite or fetch a favorite,
we will always have the server returned to you,
the whole set of favorites and then we'll simply add these favorites
into our redux store here so that's what we are doing here.
Again, the code structure should look very very familiar to you,
if you simply look at how the post favorite,
the delete favorite, and the fetch favorites are implemented.
So, all these will handle the issue of favorites.
Now, how exactly is the favorites itself implemented?
So, the reducer function is implemented in favorite structure here.
So, inside this reduced function,
you will see how we handle the add favorites,
favorites loading, and favorites failed here.
Again the code should look very familiar to you based upon
your experience with the reducer functions that you've seen for redux before.
So, again pay a little bit of attention to the way the code is implemented.
This is fairly straightforward so I'm not spending
too much time explaining how these things are implemented.
Now, taking advantage of these,
we have in the components we now have
a new favorites component whose job it is to render all the list of our favorite.
So, here you see that the favorites component itself,
the structure of the favorites component is very much similar to
the structure of the menu component so here we have
the favorites component which is implemented as a functional component and in
there we are rendering the favorites in here as you see in the code here.
Again, very straightforward I think you should be able to
easily understand how the favorites component is
implemented having had experience with how the menu component is implemented there.
So, again I'm not spending too much time explaining code here.
Now parsing through the code is also
a good experience for you to learn how the code is implemented so
processing this code in your own head will help you to understand again
to consolidate your understanding of react in more detail.
So, I will leave that as an exercise for you.
Now I'm pointing out where the changes have been
made to implement the support for favorites.
Now the favorite term,
favorites is also leverage in
the dish detail component and inside the dish detail component,
you will see that we have the additional- In here,
in the render dish functional component,
we will be rendering the button which supports
the selection or when you click on the heart outline,
it will add that particular item into your list of favorite.
So, all this is supported here by using this button here which
invokes as you see this function called post favorite which is the redux.
Thank that we have implemented there and this support for this
is implemented in the main components so when you go into the main component,
you will see how the post favorite is implemented here
and you will also see that this is
included in the map dispatched to props and so the post favorite implemented.
So, you see the structuring is very much the
same as what you've seen for the other code there.
So, I'm not going to spend too much time on how the favorites support is implemented,
instead let me spend a little more time on how
the user authorization and authentication is supported in the code here.
Now for the user authentication,
what we are doing here is that when you go into the configure store here,
you will see that I have one more reducer function called Auth that is implemented here.
So, that will track the authorization part of it.
Now how is this implemented?
Again, going into action creators,
inaction types we have already seen the set of actions related to login and logout.
So, going into action creators,
you will see that up here we have
all the functions that are implemented for logging in and logging out.
So, you will see a new function called request login, receive logging,
and so these are when the login is successful and so on but in particular,
this particular funct here of the login user is where we start with the login process.
So, we'll dispatch the request login at the point when the user tries to login,
after that we will do a fetch to the users slash login endpoint with
the post and this contains in the body of the message the credentials for the user here.
So, once we do the fetch,
if the response is correctly returned,
then the response should contain the token there.
So, we will process that response down here and then so if the login was successful,
then we will store the token into the local storage here.
So, you can see that we are saying LocalStorage set
item token response token and then we'll
also store the user's credentials in the local storage here.
So, these two will help me to track the user's login process.
After that, we will then dispatch the receive login.
Now at this point when the user is successfully logged in,
we will also fetch the favorites for the user.
Now remember that you can only fetch the favorites for a user that is logged in.
When no user is logged in there are no favorites to be fetched,
but when the user successfully logs in you want to fetch
the user's favorite so that he can display that in your react application.
So, that's why I'm also doing a fetch favorites
here and then we'll receive the login here.
Then if there is an error we'll dispatch the login error here.
So, all these functions the receive login and login error will
then invoke the appropriate Reducer functions which are implemented in the Auth.Js file.
So going into Auth.Js file,
the state here tracks the user's login status here.
So, here we will also store in the state,
the state involves the East loading Boolean which
tracks whether you are in the process of logging in. The ease authenticate-
Will indicate whether the user is authenticated and so the user is logged in,
so you'll be able to allow the user.
So, this flag is used in many circumstances
to display the user's login status and then also
the user property for the state tracks the user's credentials.
So, that is where we will get the username for display in our header component.
Now, here you will see the login request and when the login success is triggered,
then you will store the token value here and then the login failure.
The logout request, successfully logging out,
all these are handled by this various parts inside this reducer the auth.js reducer here.
So, that's how the user's authentication is handled here.
Now, in the header component,
going into the header component,
so this is where we have the login function here.
So, the handleLogin, you remember that we have
already implemented this in the react course.
In the handleLogin, they'll toggle the modal.
So, we'll close the modal and then we'll login the user at this point.
So, we'll say this.props LoginUser and then you will see that the credentials,
username and password are passed in as the parameters to
the LoginUser and so that gets into the LoginUser func,
which then takes care of logging in the user.
Now, how do you display the user's login state.
So, that is very simple again.
In the navbar here,
you will see that I have added in a new item here.
So, this is where we will say this.props.auth.isAuthenticated.
So, the isAuthenticated flag is being used here by me and so if this is set to true,
then I will display
the Logout button here and so that's the thing that I will display here.
Otherwise, I will display the login button.
So, using that isAuthenticated flag,
I am flipping which particular button is going to be displayed in
the header there whether you display the logout button or the login button.
So, that's the point that we are displaying here.
So, the login or the logout here.
So, that's how we are handling the login and logout process in
here and also we will be displaying the username right there.
So, when you display the logout button,
you will also see that we are displaying the user's name in there.
So, down below here,
we will also display the button handleLogout and
then we have the logout button being displayed here.
In addition, this particular statement here,
this is how we are displaying the username here.
So, this uses the this.props.auth.user.username.
So, the user property in the auth state contains
the user credentials and from there I fetched the username and then I
use that to display this in the header bar.
So that's the way the header component is
updated in order to handle the login and logout process.
Again, fairly straightforward ways of implementing,
it's fairly simple way that I have implemented here.
Now obviously, if you want a more complex way of handling the login and logout process,
certainly you can go into the full-fledged way of doing things,
but this is sufficient enough to meet the requirements for my application.
So, I've implemented the login and logout process in
a very simple way here using the help of the Redux store.
So, by Redux store itself is tracking
my login status whether I am logged in and I'm authenticated and whether I'm logged out.
So, if the user is logged out,
then the My Favorites is not shown here.
Now, one important point that you will ask is,
how do we ensure that we don't go into the favorites state here?
So, this is handled in the place where we handle the routes here.
So, you will notice that for the favorites here,
we declare for the favorites the endpoint instead of
calling this as the route we call it as a private route.
So, the private route allows you to ensure that you will be
allowed to go into that part only under circumstances,
where the user is logged in.
So, this will prevent a navigation to their /favorites endpoint if no user is logged in.
Now, how is this private route implemented?
This private route is implemented right up here.
So, you can see that this private route is implemented as shown here.
So, this is nothing but a route here and then in here,
we will implement this.props.auth.isAuthenticated.
So, if the user is authenticated,
then I will allow to navigate to
the component that is the favorites component.
Otherwise, I will simply redirect to the home component.
So, if no user is logged in,
I will simply redirect to the home component and so this is
implemented using this private route that I have designed here.
So, the private route is something that is supported by the router
that we use the React router Dom that we used in our React application.
So, very simple way of handling situations,
where you don't want certain routes to be navigated to when the user is not logged in.
So again, few simple changes that I have made to
the application to facilitate
all the different features that you see in your React application.
Now, as you would expect,
you might be underwhelmed at this point,
"Is it that simple to implement" and indeed that is
exactly what has been done to support all the new features.
As you see, user authentication and login and
logout process since our server has full-fledged support for everything,
implementing the client side tracking of the user logging in and
logout process and all that becomes fairly straightforward by just
modifying some of the components and adding in
the auth reducer function and adding in the auth state to our Redux store.
The whole process of handling the user authentication
and logging in and logging out becomes fairly simple in this case.
So, with this quick tour of the updated React code,
let's continue on to examine
our React application a few more features of our React application.
So again, going back to our application,
we can now go to the menu and then pull up
any dish here and I can post comments to the dish here,
so I would immediately set up the rating here and my comment value here.
Notice that I am not inputting my username or my author's name here in the form here.
Now of course, in order to submit a comment you need to be logged in.
So, if you're not logged in this comment will not be accepted by my server.
So, let me first log myself in.
So, I can login here
and the moment I login you immediately notice that
header toolbar is updated to indicate my status.
Now, I can post this comment and you would notice that when I post the comment,
the comment is added into the list of the comments
and also notice that the author field is
automatically filled in here because that is how we set up our server side.
In the comments field,
we have setup our user as a reference to
the user information that we store in
our server side and since we use the populate Mongoose Populate on the server side,
the user information is automatically populated
into the incoming comments from the server side.
So, that is how you notice how I'm leveraging
what the server already provides for me to automatically fill in the details.
So, minor changes again even into
the dish detail page to reflect the use of the comments support on the server site.
With this, I complete
the quick illustration of the React client that we have implemented as part of
this exercise and I hope that you
go through the details of the code in the client also and then
reflect back on what you've learned in React course and see how
the modifications enable us to implement in a modified,
[inaudible] which is now able to communicate with the server and then support all the features that
we originally intended to implement as part of both our client and the server side.