Hello! Welcome back.
In our last session, we successfully built a registration form, covering controlled components, client-side validation, and submitting data to an API endpoint. You learned how to structure a form, manage its state with useState, and provide user feedback during asynchronous operations.
Today, we'll build on that foundation to tackle the next crucial part of our authentication flow. Our goal is to build a login form and handle API submission for user authentication. This process will feel familiar, as it reinforces many of the patterns from the registration form, but with a critical new step: handling the successful login response to establish a user session.
1. The Login Form: Structure and State
Just like the registration form, our login form will be a controlled component. We'll need state to manage the email and password fields. The overall structure will consist of:
- Two input fields for credentials.
useStatehooks to store the values of these inputs.onChangehandlers to update the state as the user types.- An
onSubmithandler for the form that triggers our login logic.
2. Implementing the Full Login Flow
We're going to follow a video tutorial that walks through this exact process. It's a great, practical example that aligns perfectly with our project. A particularly relevant point for you is that the video's author created the backend API using Laravel, the same framework you're experienced with. This demonstrates a real-world scenario of a React frontend communicating with a Laravel backend.
Step 1: Understanding the API Endpoint
Before writing any frontend code, a good practice is to understand and test the API endpoint you'll be communicating with. The video begins by using Postman to test the /login endpoint. This helps confirm the expected request format (e.g., JSON with email and password) and the structure of the success and error responses.
React js project # Login with API
First, let's watch how to test the login API endpoint. This step ensures you know what to expect from the backend before you start integrating it into the React app.
Watch from 00:25 to 03:26. Notice the request method (POST), the URL, and the JSON body containing the email and password. Pay attention to the difference in the API's response for a successful login (HTTP 200 with user data) versus a failed one.
Step 2: Building the Form and Handling API Submission
Now, let's build the component and wire up the submission logic. The following sections of the video will guide you through:
- Creating the JSX for the email and password inputs and the login button.
- Setting up
useStatehooks foremailandpassword. - Writing an
asyncfunction (login) to handle the form submission. - Using
fetchto make aPOSTrequest to the API.
This is the core of today's lesson. You will see how async/await makes handling the promise returned by fetch clean and readable.
React js project # Login with API
This is the main part of our lesson. You will see how to build the form, manage its state, and connect it to the API.
Watch from 03:26 to 12:07. As you watch, focus on these key implementation details: State Management (05:42): The creation of email and password states using useState. Controlled Inputs (06:29): The use of onChange handlers to update the state with e.target.value. Async Function (08:46): The login function is marked async, and await is used for the fetch call. Fetch Configuration (09:02): Observe the configuration object passed to fetch, which specifies the method, headers (including Content-Type: 'application/json'), and the body. Note the use of JSON.stringify() to convert the JavaScript user object into a JSON string for the request body.
3. Managing the Authenticated State
What happens after the API confirms the user's credentials are correct? We receive the user's data, which often includes an authentication token. To keep the user logged in, we must store this information on the client-side. A common and simple method for this is using the browser's localStorage.
Data in localStorage persists even after the browser tab is closed, allowing our application to "remember" the user on their next visit.
The video continues to demonstrate exactly this: storing the user info and then redirecting them to a different page.
React js project # Login with API
Now, let's see how to handle a successful response by storing user data and redirecting the user.
Continue watching from where you left off, focusing on the section from 11:14 to 14:19. Pay close attention to: Storing Data (11:14): The use of localStorage.setItem('user-info', JSON.stringify(result)). It's crucial to stringify the data, as localStorage can only store strings. Redirection (11:47): The use of history.push('/add') to programmatically navigate the user to a new page after a successful login.
This pattern of Submit -> Await Response -> Store Token/Data -> Redirect is a fundamental flow in single-page applications.
The article below provides a high-level overview that reinforces this concept.
How to Set Up React User Authentication
This article from SuperTokens provides a general guide to React authentication. We'll look at the section on managing state to confirm the pattern we just saw.
Please read the section titled 'Managing Authentication State'. It reinforces the practice of storing JWTs (which are part of the user data we're saving) in localStorage for persistence across browser sessions.
4. A Quick Look at Form Strategies
We've consistently used "controlled" components for our forms. This is a great pattern, but it's not the only one. For context, it's worth knowing about "uncontrolled" components, where the form data is handled by the DOM itself and you pull the data out only when needed (e.g., on submission).
Given your developer background, understanding this distinction will give you a more complete picture of form handling in React.
A Better Guide To Forms in React
To broaden your understanding of React forms, this article offers an excellent comparison between controlled and uncontrolled inputs.
Read the section 'Controlled vs Uncontrolled'. You don't need to change our implementation, but understand the trade-offs. Notice how uncontrolled forms use the FormData API, which can reduce boilerplate code for very large forms.
For our login and registration forms, controlled components are a perfectly fine choice. They give us easy access to the input values at all times, which is useful for things like real-time validation.
Conclusion
Excellent work! You have now implemented the two most essential pieces of any authentication system: registration and login. You've reinforced the controlled component pattern and gained significant practice with asynchronous API calls using async/await and fetch.
Key Takeaways:
- The login form's structure and state management are very similar to the registration form, reinforcing the controlled component pattern.
async/awaitprovides a clean syntax for handling asynchronousfetchrequests.- A successful login flow involves making a
POSTrequest with user credentials and awaiting a response. - Upon success, user data and an authentication token are stored in
localStorageto persist the session. - Programmatic redirection (e.g., with React Router's
historyoruseNavigatehook) is used to move the user to a protected area of the app after login.
Preview of the Next Lesson:
Currently, our user data is in localStorage, but the rest of our application doesn't know about it yet. To make the user's authentication status globally available, we need a robust state management solution. In the next lesson, we will create a global AuthContext to provide authentication status and user data throughout the entire component tree. This will allow us to do things like show the user's name in the header and protect routes from unauthenticated access.