Janek Kruczkowski
A Comprehensive Case Study: Building a Masking Email System with React.js and Best Practices
Introduction
Email masking is an essential practice to protect users' privacy and prevent spam. In this article, we'll explore how to build a masking email system using * React.js* and best practices. React.js is a popular JavaScript library for building user interfaces, and its component-based approach makes it ideal for creating scalable applications.
Setting up the project
Prerequisites
Before starting, make sure you have the following installed:
- Node.js (version 12.x or higher)
- npm (version 6.x or higher)
Initializing the project
To create a new React.js project, run the following command in your terminal:
npx create-react-app masking-email-app
Creating the frontend
Designing the form
Create a new component called EmailForm
and include the following code:
import React from 'react';
function EmailForm() {
return (
<form>
<label htmlFor="email">Enter your email:</label>
<input type="email" id="email" required/>
<button type="submit">Mask My Email</button>
</form>
);
}
export default EmailForm;
Handling form submission
Add an onSubmit
event handler to the form and a state variable to store the email input:
import React, {useState} from 'react';
function EmailForm() {
const [email, setEmail] = useState('');
const handleSubmit = (event) => {
event.preventDefault();
// Call API to mask the email
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Enter your email:</label>
<input type="email" id="email" value={email}
onChange={(e) => setEmail(e.target.value)} required/>
<button type="submit">Mask My Email</button>
</form>
);
}
export default EmailForm;
Understanding the useReducer hook
What is useReducer?
useReducer
is a built-in React hook that manages complex state logic in
functional components. It is similar to useState
, but it is more suitable for state management when there are
multiple sub-values or when the next state depends on the previous one.
Benefits of useReducer
- Provides a more organized way to handle complex state updates
- Makes it easier to manage state transitions
- Allows for easy testing and separation of concerns
Implementing the useReducer hook
Creating the reducer function
Create a new file called emailReducer.js
and add the following code:
export const initialState = {
email: '',
maskedEmail: '',
loading: false,
error: null,
};
export const actionTypes = {
SET_EMAIL: 'SET_EMAIL',
MASK_EMAIL_REQUEST: 'MASK_EMAIL_REQUEST',
MASK_EMAIL_SUCCESS: 'MASK_EMAIL_SUCCESS',
MASK_EMAIL_FAILURE: 'MASK_EMAIL_FAILURE',
};
export const emailReducer = (state, action) => {
switch (action.type) {
case actionTypes.SET_EMAIL:
return {...state, email: action.payload};
case actionTypes.MASK_EMAIL_REQUEST:
return {...state, loading: true, error: null};
case actionTypes.MASK_EMAIL_SUCCESS:
return {...state, loading: false, maskedEmail: action.payload};
case actionTypes.MASK_EMAIL_FAILURE:
return {...state, loading: false, error: action.payload};
default:
return state;
}
};
Dispatching actions
Modify the EmailForm
component to use the useReducer
hook and dispatch actions:
import React, {useReducer} from 'react';
import {emailReducer, initialState, actionTypes} from './emailReducer';
function EmailForm() {
const [state, dispatch] = useReducer(emailReducer, initialState);
const handleSubmit = async (event) => {
event.preventDefault();
dispatch({type: actionTypes.MASK_EMAIL_REQUEST});
try {
// Call API to mask the email
// Assume the API returns a response with the masked email
const response = await fetch('/api/mask', {
method: 'POST',
body: JSON.stringify({email: state.email}),
});
const data = await response.json();
dispatch({
type: actionTypes.MASK_EMAIL_SUCCESS,
payload: data.maskedEmail
});
} catch (error) {
dispatch({
type: actionTypes.MASK_EMAIL_FAILURE,
payload: error.message
});
}
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Enter your email:</label>
<input
type="email"
id="email"
value={state.email}
onChange={(e) => dispatch({
type: actionTypes.SET_EMAIL,
payload: e.target.value
})}
required
/>
<button type="submit">Mask My Email</button>
</form>
);
}
export default EmailForm;
Setting up the backend
Backend technologies
For the backend, we will use Node.js and Express.js. Create a new folder
called backend
and initialize a new Node.js project:
mkdir backend
cd backend
npm init -y
Install the required packages:
npm install express cors body-parser
Creating API routes
Create a new file called app.js
and set up the basic Express.js server:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.post('/api/mask', (req, res) => {
// Mask email logic will be here
});
app.listen(3001, () => console.log('Server running onport 3001'));
Masking the email
Understanding the masking process
Email masking involves replacing a portion of the email address with a specific character (e.g., asterisks) to hide the actual email address. This protects the user's privacy and prevents spam.
Implementing email masking
Add the following email masking function to your app.js
file:
function maskEmail(email) {
const [localPart, domain] = email.split('@');
const maskedLocalPart = localPart.slice(0, 3) + '*'.repeat(localPart.length - 3);
return maskedLocalPart + '@' + domain;
}
Update the /api/mask
route to use the maskEmail
function:
app.post('/api/mask', (req, res) => {
const email = req.body.email;
const maskedEmail = maskEmail(email);
res.json({maskedEmail});
});
Connecting the frontend and backend
Fetch API
Update the EmailForm
component's handleSubmit
function to send a request to the backend:
const response = await fetch('http://localhost:3001/api/mask', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({email: state.email}),
});
Handling API responses
Display the masked email and any errors in the EmailForm
component:
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Enter your email:</label>
<input
type="email"
id="email"
value={state.email}
onChange={(e) => dispatch({
type: actionTypes.SET_EMAIL,
payload: e.target.value
})}
required
/>
<button type="submit">Mask My Email</button>
{state.maskedEmail && <p>Masked Email: {state.maskedEmail}</p>}
{state.error && <p>Error: {state.error}</p>}
</form>
);
Implementing best practices
Code organization
Organize your code into folders and files that separate concerns:
-
Components:
src/components
-
Reducers:
src/reducers
-
API calls:
src/api
Error handling
Handle errors gracefully by displaying user-friendly error messages and logging errors for debugging purposes.
Testing the application
Unit tests
Write unit tests for your components, reducers, and utility functions using Jest and React Testing Library.
Integration tests
Perform end-to-end testing using tools like Cypress to ensure that the entire application works as expected.
Deploying the application
Deployment options
Choose a suitable deployment platform for your frontend (e.g., Netlify, Vercel) and backend (e.g., Heroku, AWS Lambda).
Continuous integration
Set up a CI/CD pipeline to automate the deployment process and ensure that your application is always up-to-date.
Conclusion
In this article, we've built a masking email system using React.js and best practices. We've discussed the useReducer hook, demonstrated how to connect the frontend and backend, and provided code examples to guide you through the process. This beginner-friendly guide should have given you a solid understanding of how to create a masking email application using React.js.
FAQs
-
What is email masking? Email masking is a technique to hide a portion of an email address to protect the user's privacy and prevent spam.
-
Why should I use React.js for this project? React.js is a popular JavaScript library that simplifies building user interfaces, making it an ideal choice for creating scalable applications.
-
What is the useReducer hook? The useReducer hook is a built-in React hook for managing complex state logic in functional components. It is particularly useful when managing multiple sub-values or when the next state depends on the previous one.
-
How does the masking email function work? The masking email function splits the email into the local part and domain, then replaces a portion of the local part with a specific character (e.g., asterisks) to hide the actual email address.
-
What should I consider when deploying the application? Choose a suitable deployment platform for your frontend (e.g., Netlify, Vercel) and backend (e.g., Heroku, AWS Lambda), and set up a CI/CD pipeline to automate the deployment process and ensure that your application is always up-to-date.