Build a Next.js Interactive Web-Based BMI Calculator

Written by

in

In the age of health consciousness, understanding and tracking your Body Mass Index (BMI) has become increasingly important. BMI is a simple calculation that uses a person’s height and weight to estimate body fat. Building a BMI calculator isn’t just a useful project for personal use; it’s also a fantastic way to learn and practice web development skills using Next.js. This tutorial will guide you, step-by-step, through creating an interactive BMI calculator application, perfect for beginners and intermediate developers looking to expand their Next.js knowledge.

Why Build a BMI Calculator?

Creating a BMI calculator provides several benefits:

  • Practical Application: You’ll build something you can use and potentially share.
  • Learn Core Concepts: You’ll gain hands-on experience with fundamental web development principles like user input, calculations, and displaying results.
  • Next.js Mastery: You’ll familiarize yourself with key Next.js features such as component structure, state management, and basic styling.
  • Portfolio Piece: It’s a project you can showcase to demonstrate your skills to potential employers or clients.

Prerequisites

Before we dive in, ensure you have the following:

  • Node.js and npm (or yarn): Installed on your computer. These are essential for managing project dependencies and running the development server.
  • Basic HTML, CSS, and JavaScript knowledge: Familiarity with these languages will help you understand the code and concepts.
  • A code editor: Such as Visual Studio Code, Sublime Text, or Atom.

Setting Up the Next.js Project

Let’s start by creating a new Next.js project. Open your terminal and run the following command:

npx create-next-app bmi-calculator
cd bmi-calculator

This command creates a new Next.js project named “bmi-calculator” and navigates you into the project directory. Next.js will automatically set up the basic project structure for you.

Project Structure Overview

Your project directory should look something like this:

bmi-calculator/
├── node_modules/
├── pages/
│   ├── _app.js
│   ├── index.js
│   └── api/
│       └── hello.js
├── public/
│   └── ...
├── .gitignore
├── next.config.js
├── package-lock.json
├── package.json
└── README.md
  • pages/: This directory is the heart of your Next.js application. Files within this directory become routes. For example, pages/index.js will be accessible at the root path (/).
  • public/: This directory holds static assets like images, fonts, etc.
  • package.json: Contains project metadata and dependencies.

Building the BMI Calculator Component

Now, let’s create the core component for our BMI calculator. We’ll modify the pages/index.js file.

Open pages/index.js and replace its content with the following code:

import { useState } from 'react';

export default function Home() {
  const [weight, setWeight] = useState('');
  const [height, setHeight] = useState('');
  const [bmi, setBmi] = useState(null);
  const [category, setCategory] = useState('');

  const calculateBMI = () => {
    if (!weight || !height) {
      alert('Please enter both weight and height.');
      return;
    }

    const weightInKg = parseFloat(weight);
    const heightInM = parseFloat(height) / 100; // Convert cm to meters

    if (isNaN(weightInKg) || isNaN(heightInM) || weightInKg <= 0 || heightInM <= 0) {
        alert('Please enter valid positive numbers for weight and height.');
        return;
    }

    const calculatedBmi = weightInKg / (heightInM * heightInM);
    setBmi(calculatedBmi.toFixed(2));

    let bmiCategory = '';
    if (calculatedBmi = 18.5 && calculatedBmi = 25 && calculatedBmi  setWeight(e.target.value)}
          style={{ marginLeft: '10px', padding: '5px', borderRadius: '5px', border: '1px solid #ccc' }}
        />
      </div>
      <div style={{ marginBottom: '15px' }}>
        <label htmlFor="height">Height (cm): </label>
        <input
          type="number"
          id="height"
          value={height}
          onChange={(e) => setHeight(e.target.value)}
          style={{ marginLeft: '10px', padding: '5px', borderRadius: '5px', border: '1px solid #ccc' }}
        />
      </div>
      <button onClick={calculateBMI}
              style={{ padding: '10px 20px', backgroundColor: '#4CAF50', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }}
      >Calculate BMI</button>
      {bmi !== null && (
        <div style={{ marginTop: '20px' }}>
          <p>Your BMI: {bmi}</p>
          <p>Category: {category}</p>
        </div>
      )}
    </div>
  );
}

Let’s break down this code:

  • Import useState: This hook from React allows us to manage the state of our component. We’ll use it to store the weight, height, BMI, and category.
  • State Variables:
    • weight: Stores the user’s weight input (in kg).
    • height: Stores the user’s height input (in cm).
    • bmi: Stores the calculated BMI value.
    • category: Stores the BMI category (e.g., “Underweight”, “Normal weight”).
  • calculateBMI Function:
    • Retrieves weight and height values from the input fields.
    • Validates the input to ensure it’s valid numbers and positive.
    • Converts height from cm to meters.
    • Calculates the BMI using the formula: weight (kg) / (height (m) * height (m)).
    • Rounds the BMI to two decimal places.
    • Determines the BMI category based on the calculated BMI.
    • Updates the state variables bmi and category.
  • JSX Structure:
    • Creates input fields for weight and height.
    • Uses the onChange event handler to update the state variables when the user types in the input fields.
    • Includes a button that calls the calculateBMI function when clicked.
    • Conditionally renders the BMI result and category if the bmi state variable is not null.

Running the Application

To run your application, open your terminal, navigate to your project directory (bmi-calculator), and run the following command:

npm run dev

This command starts the Next.js development server. Open your web browser and go to http://localhost:3000. You should see your BMI calculator application in action.

Adding Basic Styling

The code above includes basic inline styling for simplicity. For a more organized and maintainable approach, you can create a separate CSS file or use a CSS-in-JS solution. Let’s create a simple CSS file to improve the look of our calculator. In the root directory of your project, create a file named styles/Home.module.css and add the following code:


.container {
  font-family: sans-serif;
  padding: 20px;
}

.input-group {
  margin-bottom: 15px;
}

label {
  margin-right: 10px;
}

input[type="number"] {
  padding: 5px;
  border-radius: 5px;
  border: 1px solid #ccc;
  margin-left: 10px;
}

button {
  padding: 10px 20px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

button:hover {
  background-color: #3e8e41;
}

.result {
  margin-top: 20px;
}

Now, import this CSS file into your pages/index.js file. Modify the import statement at the top of your pages/index.js file to include the CSS module:

import styles from '../styles/Home.module.css';

And then apply the styles to the corresponding elements:


<div className={styles.container}>
  <h2>BMI Calculator</h2>
  <div className={styles['input-group']}>
    <label htmlFor="weight">Weight (kg): </label>
    <input
      type="number"
      id="weight"
      value={weight}
      onChange={(e) => setWeight(e.target.value)}
    />
  </div>
  <div className={styles['input-group']}>
    <label htmlFor="height">Height (cm): </label>
    <input
      type="number"
      id="height"
      value={height}
      onChange={(e) => setHeight(e.target.value)}
    />
  </div>
  <button onClick={calculateBMI}>Calculate BMI</button>
  {bmi !== null && (
    <div className={styles.result}>
      <p>Your BMI: {bmi}</p>
      <p>Category: {category}</p>
    </div>
  )}
</div>

Restart your development server (npm run dev) and refresh your browser. You should see a more visually appealing BMI calculator.

Handling User Input and Validation

User input validation is crucial to ensure the accuracy and reliability of your application. In our BMI calculator, we’ve already included some basic validation:

  • Empty Input Check: The calculateBMI function checks if both weight and height are provided.
  • Numeric Input Check: The parseFloat() function attempts to convert the input to numbers. If the conversion fails (e.g., the user enters text), isNaN() will return true, and an error message will be shown.
  • Positive Number Check: The code checks if the weight and height are positive values.

You can enhance the validation further by:

  • Implementing client-side validation: Use JavaScript to validate the input in real-time as the user types, providing immediate feedback.
  • Adding more specific error messages: Instead of a generic “Please enter valid numbers,” provide more informative messages (e.g., “Weight must be a positive number.”).
  • Preventing invalid characters: Use input types like number and potentially regular expressions to restrict the characters the user can enter.

Deploying Your Application

Once you’ve built and tested your BMI calculator, you’ll likely want to deploy it so others can use it. Next.js makes deployment straightforward. Here are a few options:

  • Vercel: Vercel is the platform created by the Next.js team. It offers seamless deployment, automatic builds, and free hosting for personal projects. It’s the easiest way to deploy a Next.js app.
  • Netlify: Another popular platform for deploying web applications. Netlify also provides easy deployment and automatic builds.
  • Other Hosting Providers: You can also deploy your Next.js application to other platforms like AWS, Google Cloud, or Azure, but this requires more configuration.

To deploy to Vercel, simply push your code to a Git repository (e.g., GitHub, GitLab, or Bitbucket) and then import the repository into Vercel. Vercel will automatically build and deploy your application.

Common Mistakes and Troubleshooting

Here are some common mistakes and how to fix them:

  • Incorrect Import Paths: Double-check your import paths, especially when importing CSS modules or components.
  • Typographical Errors: Typos in variable names, function names, or JSX attributes can cause errors.
  • State Updates Not Working: Ensure you’re correctly using the useState hook to update the state.
  • CSS Issues: Make sure your CSS file is correctly linked and that your CSS selectors are targeting the correct elements. Browser developer tools are invaluable for debugging.
  • Input Validation Errors: Thoroughly test your input validation to catch edge cases and ensure your application handles invalid input gracefully.

Key Takeaways and Best Practices

Here’s a summary of what you’ve learned and some best practices:

  • Next.js Fundamentals: You’ve used Next.js to create a basic application with routes, components, and state management.
  • Component Structure: You’ve learned how to break down your application into reusable components.
  • State Management: You’ve used the useState hook to manage component state.
  • User Input and Validation: You’ve implemented basic input validation to ensure data integrity.
  • Styling: You’ve learned how to add styling using both inline styles and CSS modules.
  • Deployment: You’ve learned about deploying a Next.js application.
  • Clean Code: Write clean, readable code with comments.
  • Test Thoroughly: Test your application with different inputs to ensure it works correctly.
  • Use Developer Tools: Use your browser’s developer tools to debug and inspect your code.

FAQ

Here are some frequently asked questions:

  1. Can I customize the BMI categories? Yes, you can modify the calculateBMI function to include different BMI categories or adapt the categories based on specific demographics.
  2. How can I add unit selection (e.g., imperial units)? You can add input fields for feet/inches and pounds and then convert them to metric units before the BMI calculation.
  3. How do I make the calculator responsive? Use CSS media queries to adjust the layout and styling of your calculator for different screen sizes.
  4. Can I store the BMI results? Yes, you can use local storage, cookies, or a database to store the BMI results for later retrieval.
  5. Where can I learn more about Next.js? The official Next.js documentation is an excellent resource: https://nextjs.org/docs.

Congratulations! You’ve successfully built a fully functional BMI calculator using Next.js. This project is a solid foundation for learning web development and Next.js. You can now adapt and expand upon this project by adding more features, refining the design, or integrating it with other applications. As you continue your web development journey, remember to practice regularly, experiment with new technologies, and don’t be afraid to make mistakes. Each project you undertake will contribute to your growing expertise and allow you to build increasingly sophisticated web applications. The skills you’ve gained in this tutorial, from understanding component structure and managing state to handling user input and deploying your application, will be invaluable as you tackle more complex projects in the future. Embrace the process of learning and building, and enjoy the satisfaction of creating something useful and interactive.