Challenges Faced During Development of the MERN Stack E-Commerce Application

While building the MERN Stack e-commerce application, several errors and obstacles cropped up along the way. However, through careful troubleshooting and research, I was able to resolve these issues effectively. Below are the common challenges I faced during the project and how I handled them:


1. MongoDB Connection Issues

Error: The app failed to connect to MongoDB, resulting in an error like MongoNetworkError: failed to connect to server [localhost:27017] on first connect.

Solution: I first checked the MongoDB server status to ensure it was running on my machine. When the server was running, I realized that there was a configuration mismatch in the MongoDB URI inside the config/db.js file.

How I Fixed It:

  1. I checked that the correct URI was used. If using a local database, I ensured that the URI matched mongodb://localhost:27017/closet_cater_db.

  2. I added the necessary MongoDB options to the connection, such as useNewUrlParser: true and useUnifiedTopology: true to ensure compatibility with the latest MongoDB driver.

  3. If I were deploying to production, I made sure the URI pointed to MongoDB Atlas and that my connection string included the username and password for the database.

const mongoose = require('mongoose');

const connectDB = async () => {
  try {
    await mongoose.connect('mongodb://localhost:27017/closet_cater_db', {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    });
    console.log('MongoDB Connected');
  } catch (error) {
    console.error(error);
    process.exit(1); // Exit with failure
  }
};

module.exports = connectDB;

2. CORS Issues with API Calls

Error: The frontend React app was making API calls to the backend, but I encountered CORS errors like Access-Control-Allow-Origin header is missing.

Solution: This is a common issue when the frontend and backend are running on different ports (e.g., React on port 3000 and Node.js on port 5000).

How I Fixed It:

  1. I installed the CORS middleware in the backend (express app) and configured it to allow requests from the frontend development server.
npm install cors
  1. In the backend/server.js, I added the CORS middleware to allow the frontend to communicate with the backend.
const cors = require('cors');
app.use(cors({ origin: 'http://localhost:3000' })); // Allow requests from React app

This allowed the frontend to access the backend API without running into CORS-related errors.


3. JWT Authentication Token Errors

Error: When implementing user login and authentication, I faced issues related to invalid or expired JWT tokens, resulting in Unauthorized errors when making API requests.

Solution:

  1. I made sure that JWT tokens were being generated correctly after user login and stored in the frontend’s local storage.

  2. The problem occurred when the token was not sent with every API request to secure endpoints. To fix this, I added the token to the Authorization header in the fetch requests in React.

const token = localStorage.getItem('authToken');
fetch('/api/protected-route', {
  headers: {
    'Authorization': `Bearer ${token}`,
  },
})
  1. On the backend, I implemented the JWT verification middleware to check the token before accessing secure routes. This middleware helped ensure that requests without valid tokens were blocked.
const jwt = require('jsonwebtoken');

const authMiddleware = (req, res, next) => {
  const token = req.header('Authorization')?.split(' ')[1]; // Bearer token format
  if (!token) {
    return res.status(401).json({ message: 'Unauthorized' });
  }
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded.user; // Attach user info to request
    next();
  } catch (error) {
    return res.status(401).json({ message: 'Invalid token' });
  }
};

This ensured smooth authentication and authorization flow.


4. Redux State Management and React Component Re-Renders

Error: My application experienced unnecessary re-renders of components and stale state when using Redux to manage global state.

Solution: The issue was caused by improper usage of the useEffect hook and state management in Redux.

How I Fixed It:

  1. I used the useSelector hook to retrieve state from Redux and useDispatch to dispatch actions.

  2. To optimize performance, I ensured that components subscribed to only the specific slices of the state they needed rather than the entire store, reducing unnecessary re-renders.

  3. I also used the memoization techniques such as React.memo() to wrap components that didn’t need to re-render unless specific props changed.

Example:

const CartPage = React.memo(() => {
  const cartItems = useSelector((state) => state.cart.items);
  return (
    <div>
      {cartItems.map(item => (
        <CartItem key={item.id} {...item} />
      ))}
    </div>
  );
});

This improved performance by limiting component re-renders and ensuring that only relevant components were updated when necessary.


5. React Build Warnings

Error: During the production build (npm run build), I encountered ESLint warnings about unused variables like 'response' is assigned a value but never used.

Solution: These warnings didn’t stop the build, but they were noisy and could potentially lead to issues in the future.

How I Fixed It:

  1. I went through the affected files (AdminPage.jsx, OrderPage.jsx, etc.) and removed the unused variables or added eslint-disable-next-line comments where appropriate.

  2. For unused imports, I removed them entirely from the files.

// eslint-disable-next-line no-unused-vars
const response = await fetch(...);

I also made sure that the React components were clean and efficient by removing unused code.


6. Deployment Problems

Error: When deploying the app, I faced some environment variable mismatches between the development and production environments, especially with the MongoDB URI and JWT secrets.

Solution:

  1. I created .env files for both frontend and backend:

    • Backend .env file contained secrets for the JWT_SECRET and MongoDB URI.

    • Frontend .env file stored the API base URL to ensure correct API routing in production.

  2. On deployment, I ensured that these environment variables were correctly set in the Heroku (for backend) and Netlify/Vercel (for frontend) dashboards.

MONGODB_URI=mongodb://localhost:27017/closet_cater_db
JWT_SECRET=mysecretkey

This solved the deployment issues and allowed both frontend and backend to function correctly in production.

app here: https://github.com/EkeminiThompson/ecommerce


Conclusion

The process of developing and deploying a MERN stack e-commerce app comes with its share of challenges, especially when dealing with authentication, data management, and deployment. However, each challenge helped me grow as a developer and taught me useful strategies for solving real-world issues. By addressing errors like MongoDB connection issues, JWT token handling, CORS problems, Redux state management, and deployment environment setup, I was able to create a smooth and fully functional e-commerce application that can handle production-level traffic.

0
Subscribe to my newsletter

Read articles from Ekemini Thompson directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ekemini Thompson
Ekemini Thompson

Ekemini Thompson is a Machine Learning Engineer and Data Scientist, specializing in AI solutions, predictive analytics, and healthcare innovations, with a passion for leveraging technology to solve real-world problems.