In the previous part of this tutorial, How to Build a Login/Register App with the MERN Stack (Part 4): Setting Up Frontend Routes, we created our Frontend pages with React. In this part, we will connect Frontend to Backend using React’s Context API.
Creating Users Context
Basic Component
First, let’s create a contexts
folder in client/src
, and create a Users.js
file inside it. After that, let’s create a regular Class Component
called UsersContextProvider
.
To be able to complete this component and write its render
lifecycle method, we need to create a context first.
As you can see, we created a context on line
3
using React.createContext()
. Then, we return a provider of that context in the render method, passing the value of this.state
to the children of this provider. We also render the children components that get passed to this provider, as shown on line 21
, so that we can wrap other components with this component. Finally, we export the context itself along with the provider component.
To actually make this context useful, we need to define the methods we mentioned on lines 12
, 13
, and 14
. But before we go ahead and implement them, let’s define a constant called API_URL
to make it easier to mention the API URL any where in this context’s code.
const API_URL = process.env.NODE_ENV === 'production' ? 'PRODUCTION_URL' : 'http://localhost:5000';
NOTE: We will replace that ‘PRODUCTION_URL‘ placeholder later.
The logUserIn Method
This method is supposed to return an object containing title
and text
properties. These properties will be used alongside with sweetalert-react
to show nice alerts to the user. So, first, we send a POST
request to the login
endpoint of the API
. We specify the Content-Type
to be application/json
so that the server can parse data correctly. We send Cookies
along with this request, so that the server can use our session
data, by setting the credentials
option to 'include'
. And we also send the username
and password
as body of this request. On line 14
, we get out data from the response we got back. We do some basic processing, based on how we wrote the API endpoints, for the status code
we got. If every thing went well, we update the state
to have isLoggedIn
set to true
, and store user
info we got back.
The registerUser Method
This method is also supposed to return a similar object to that returned by logUserIn
method. First, we do very basic validation for the data, you can go beyond this if you want. If the data is OK, we send them via a POST
request to the register
endpoint of the API
. Finally, we process the status code we get from that request and set different values for title
and text
based on each condition.
The logUserOut Method
Although this method is very simple, it is extremely important to send cookies
along with the request to the logout
endpoint of the API
, so that the server can destroy the session of the client sending that request.
The componentDidMount Lifecycle Method
We will use this lifecycle method to make sure users can’t just open a new tab and go to the login or register page when they are already logged in. We make a GET
request to the currentUser
endpoint of the API
, and update the state with the received data.
Using Users Context
To make components in our app able to use data in Users
context, we need to import
UsersContextProvider
component into client/index.js
. And then wrap the App
component with it.
Finishing Up Pages Components
Creating NavBar Component
In your src/components
folder, create a NavBar
folder and put the following lines in a NavBar.js
file inside it.
As you can see, this is a very basic component that renders a NavBar with a button in it. To be able to use the logUserOut
method from the Users
context, we first need to import
the context
. Then, assign the UsersContext
to a static class field
called contextType
. And now, we can access the data provided by this context through this.context
. So, we set the onClick
prop of the button to be this.context.logUserOut
. Easy! Right?
And this is NavBar.css
:
Re-creating Home Page
Now we have Users
context, let’s re-create the Home
page.
At first, we do the very basic context setup. Then, in the render method we check if the user is not logged in, if they are not, we redirect them to the login page. Otherwise, we return the NavBar and a welcome message with the username in it.
And here is Home.css
:
Finishing Up Login Page
Alright, let’s finish up the parts of login page component that depend on Users
context.
First, add these import
lines to the top of your Login.js
.
import { UsersContext } from '../../contexts/Users'; import { Redirect } from 'react-router-dom'; import SweetAlert from 'sweetalert-react'; import 'sweetalert/dist/sweetalert.css';
Then, declare contextType
as usual, and add this object to the state
.
alert: { showAlert: false, title: '', text: '', }
Afterwards, change the handleFormSubmit
method to be:
We get the username
and password
from the state
, pass them to the logUserIn
function we get from the context
, and update the state
with what we get back.
Finally, we need to update the render
method as shown below:
We redirect the user if they are logged in to the home page on line 3
. We also render the SweetAlert component as shown on lines 10-15
. You can read sweetalert-react
‘s documentation to know how to use it.
Finishing Up Register page
We do the exact same thing we did for Login.js
to Register.js
, except for the handleFormSubmit
method.
Conclusion
First, we learnt about the Context API
and created our Users
context. Then, we added some methods to it to make it easier to connect Frontend to Backend. Finally, we completed working on the pages and components that needed the Users
context. In the next part of this tutorial, we will finally deploy this app to Heroku.
NOTE: You can find all parts of this tutorial here and code here.