React Website Auth & Registration
Budget: $30 – $250 USD
Add registration and authorization logic
Add forms for signing up and signing in
Let’s review React and JSX. We need to add new components according to the design:
RegisterModal is the component for user registration with the necessary state variables
LoginModal is the component for user authorization with the necessary state variables
You can use your existing AddItemModal as a model for these new components, but pay attention to the type attribute of the input elements. The email input should have type="email", and the password input should have type="password".
Most of the requests used in your application (such as liking or deleting cards, or creating new cards) should only be available to authorized users. The only exception is the GET /items request, which should be run on page load regardless of whether a user is logged in.
You'll implement two new requests to the server for unauthorized users in a separate auth.js file:
If an unauthorized user visits the application, they should only see the main page without access to the profile page and the ability to manipulate clothing items. For now, don’t worry about changes in the interface for users who have signed in and who have not — we’ll get to that a bit later.
Protect the /profile route by creating a wrapper component that redirects unauthorized users to the main page.
Configure user registration in App.jsx
Create a corresponding function for processing registration in App.jsx. Pass the values from RegisterModal's form to the request.
After successful registration, you'll need to close the modal window and immediately sign the user in.
Configure user authorization in App.jsx
Create a function to pass the necessary data to the /signin request. If a log-in attempt is successful, check that the server gave access in its response and add it to localStorage:
Check the token
Use the useEffect() hook to check if there is a token in localStorage. If a token is found there, check its validity with the server. Add the new request to auth.js. The endpoint is /users/me:
Protect API calls with the token
In the previous project, you protected routes on the backend, and this time you'll also want to make sure to protect the corresponding API calls on the frontend. You'll do this by passing the token as a parameter to the corresponding functions and adding the token to the authorization header of every request, except the following:
2. Add a current user context
Create a new context object called CurrentUserContext in the contexts folder to keep the data about the current user. Import this object into App and use its provider. Wrap all the current content of the root component with it. Use currentUser state variable as the context value for the provider:
Update the Header component
Note that the navigation bar should be different for authorized and non-authorized users. Authorized users will see their name and avatar. Use the current user context value to render the header contents accordingly.
If there is no image provided by a user, the UI will look silly. Create a placeholder with the user name’s first letter in a circle.
Update the ItemModal component
Similarly, subscribe the ItemModal component to the context to check if the delete button should be shown in the item modal. To do this, you can use the following code:
Update the ClothesSection component
Likewise, update this component to show only the cards added by the current user.
3. Add the editing profile logic
Add the EditProfileModal component for editing user data. The modal windows should be opened when the user clicks the “Edit profile” button on the profile page. The current user’s data should be filled in the form. Make an API call that sends new user name and the avatar URL to the server.
4. Add likes and dislikes
Since the list of items is stored in the clothingItems state variable of the App component, let's put the logic there. Use the following code for the handleCardLike() function that we prepared as a reference. Your variable names and code logic can be different:
After you declare the handleCardLike() function in App.js:
Pass it as a prop called onCardLike() to the Main and ItemCard components.
Inside the ItemCard component, create another function. Call this one handleLike().
In this function, call the onCardLike() function, and pass it the item data as an argument, in the same way as you did with the handleClick() handler.
If everything is done correctly, you'll see the magic of the declarative approach: after sending the data to the server, you don't have to update the DOM — you make changes to the state, and the interface will be updated automatically.
Update the ItemCard component
Hide the like button from unauthorized users. Also, make sure that the like button is always active if the user has liked the card. The following code will help to detect if the user has already liked this card:
5. Implement sign out
There’s another button on the profile page: “Sign out.” When the user clicks it, the token should be removed from local storage, and the isLoggedIn variable should be set to false.
Add forms for signing up and signing in
Let’s review React and JSX. We need to add new components according to the design:
RegisterModal is the component for user registration with the necessary state variables
LoginModal is the component for user authorization with the necessary state variables
You can use your existing AddItemModal as a model for these new components, but pay attention to the type attribute of the input elements. The email input should have type="email", and the password input should have type="password".
Most of the requests used in your application (such as liking or deleting cards, or creating new cards) should only be available to authorized users. The only exception is the GET /items request, which should be run on page load regardless of whether a user is logged in.
You'll implement two new requests to the server for unauthorized users in a separate auth.js file:
If an unauthorized user visits the application, they should only see the main page without access to the profile page and the ability to manipulate clothing items. For now, don’t worry about changes in the interface for users who have signed in and who have not — we’ll get to that a bit later.
Protect the /profile route by creating a wrapper component that redirects unauthorized users to the main page.
Configure user registration in App.jsx
Create a corresponding function for processing registration in App.jsx. Pass the values from RegisterModal's form to the request.
After successful registration, you'll need to close the modal window and immediately sign the user in.
Configure user authorization in App.jsx
Create a function to pass the necessary data to the /signin request. If a log-in attempt is successful, check that the server gave access in its response and add it to localStorage:
Check the token
Use the useEffect() hook to check if there is a token in localStorage. If a token is found there, check its validity with the server. Add the new request to auth.js. The endpoint is /users/me:
Protect API calls with the token
In the previous project, you protected routes on the backend, and this time you'll also want to make sure to protect the corresponding API calls on the frontend. You'll do this by passing the token as a parameter to the corresponding functions and adding the token to the authorization header of every request, except the following:
2. Add a current user context
Create a new context object called CurrentUserContext in the contexts folder to keep the data about the current user. Import this object into App and use its provider. Wrap all the current content of the root component with it. Use currentUser state variable as the context value for the provider:
Update the Header component
Note that the navigation bar should be different for authorized and non-authorized users. Authorized users will see their name and avatar. Use the current user context value to render the header contents accordingly.
If there is no image provided by a user, the UI will look silly. Create a placeholder with the user name’s first letter in a circle.
Update the ItemModal component
Similarly, subscribe the ItemModal component to the context to check if the delete button should be shown in the item modal. To do this, you can use the following code:
Update the ClothesSection component
Likewise, update this component to show only the cards added by the current user.
3. Add the editing profile logic
Add the EditProfileModal component for editing user data. The modal windows should be opened when the user clicks the “Edit profile” button on the profile page. The current user’s data should be filled in the form. Make an API call that sends new user name and the avatar URL to the server.
4. Add likes and dislikes
Since the list of items is stored in the clothingItems state variable of the App component, let's put the logic there. Use the following code for the handleCardLike() function that we prepared as a reference. Your variable names and code logic can be different:
After you declare the handleCardLike() function in App.js:
Pass it as a prop called onCardLike() to the Main and ItemCard components.
Inside the ItemCard component, create another function. Call this one handleLike().
In this function, call the onCardLike() function, and pass it the item data as an argument, in the same way as you did with the handleClick() handler.
If everything is done correctly, you'll see the magic of the declarative approach: after sending the data to the server, you don't have to update the DOM — you make changes to the state, and the interface will be updated automatically.
Update the ItemCard component
Hide the like button from unauthorized users. Also, make sure that the like button is always active if the user has liked the card. The following code will help to detect if the user has already liked this card:
5. Implement sign out
There’s another button on the profile page: “Sign out.” When the user clicks it, the token should be removed from local storage, and the isLoggedIn variable should be set to false.