Build a Simple Next.js Interactive Web-Based Star Rating Component

Written by

in

In today’s digital landscape, user feedback is gold. Websites and applications thrive on understanding user experiences, and a star rating system is a simple yet powerful tool for gathering this critical information. Imagine a scenario: you’re building an e-commerce site, and you want customers to rate products. Or perhaps you’re creating a review platform where users can share their opinions. In both cases, a star rating component becomes essential. This tutorial will walk you through building a fully functional, interactive star rating component using Next.js, a popular React framework. We’ll cover everything from the initial setup to handling user interactions and displaying the selected rating. By the end, you’ll have a reusable component that you can easily integrate into your projects.

Why Build a Star Rating Component?

Star ratings offer several benefits:

  • User-Friendly: They provide an intuitive way for users to express their opinions.
  • Data Collection: They gather valuable feedback that can be used to improve products, services, or content.
  • Visual Appeal: They enhance the visual presentation of a website or application.
  • SEO Benefits: Star ratings can improve search engine optimization (SEO) by adding rich snippets to search results.

Next.js is an excellent choice for this project due to its server-side rendering (SSR), static site generation (SSG), and easy-to-use routing system. These features make it easier to build performant and SEO-friendly web applications.

Prerequisites

Before you start, make sure you have the following:

  • Node.js and npm (or yarn) installed on your machine.
  • Basic knowledge of JavaScript, HTML, and CSS.
  • A code editor (e.g., VS Code, Sublime Text).

Setting Up Your 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 star-rating-app
cd star-rating-app

This command creates a new Next.js project named “star-rating-app”. Navigate to the project directory using the cd command.

Creating the Star Rating Component

Now, let’s create the star rating component. Inside your project directory, create a new folder called components. Inside the components folder, create a file named StarRating.js. This is where we’ll write the code for our component.

Here’s the basic structure of the StarRating.js file:

import React, { useState } from 'react';

function StarRating({ totalStars = 5 }) {
  const [rating, setRating] = useState(0);

  return (
    <div>
      {/* Stars will go here */}
    </div>
  );
}

export default StarRating;

Let’s break down the code:

  • We import the useState hook from React. This hook allows us to manage the component’s state (in this case, the rating).
  • We define a functional component called StarRating. It accepts a prop called totalStars, which defaults to 5.
  • We initialize the rating state variable to 0 using useState(0).
  • The component returns a div element, which will contain the star elements.

Implementing the Star Icons

Now, let’s add the star icons. We’ll use Unicode characters for the stars. Inside the StarRating.js file, modify the return statement as follows:

<div>
  {Array(totalStars).fill(0).map((_, index) => (
    <span
      key={index}
      style={{
        cursor: 'pointer',
        fontSize: '2rem',
        color: index < rating ? 'gold' : 'gray',
      }}
      onClick={() => setRating(index + 1)}
    >
      ★ {/* Filled star */} 
    </span>
  ))}
</div>

Here’s what’s happening:

  • We use the Array(totalStars).fill(0).map() pattern to create an array of star elements. This allows us to dynamically render the correct number of stars based on the totalStars prop.
  • For each star, we render a span element.
  • We set the cursor style to “pointer” to indicate that the stars are clickable.
  • We set the fontSize to “2rem” to control the size of the stars.
  • We use a conditional style to change the color of the stars based on the current rating. If the star’s index is less than the rating, it’s filled (gold); otherwise, it’s empty (gray).
  • We attach an onClick event handler to each star. When a star is clicked, the setRating function updates the rating state to the index of the clicked star plus 1.
  • We use the Unicode character ★ to represent a filled star.

Adding Hover Effects

To enhance the user experience, let’s add a hover effect to the stars. This will provide visual feedback as the user moves their mouse over the stars. Modify the StarRating.js file as follows:

import React, { useState, useRef } from 'react';

function StarRating({ totalStars = 5 }) {
  const [rating, setRating] = useState(0);
  const [hoverRating, setHoverRating] = useState(0);
  const starRef = useRef(null);

  return (
    <div>
      {Array(totalStars).fill(0).map((_, index) => (
        <span
          key={index}
          ref={starRef}
          style={{
            cursor: 'pointer',
            fontSize: '2rem',
            color: index < (hoverRating || rating) ? 'gold' : 'gray',
          }}
          onClick={() => setRating(index + 1)}
          onMouseEnter={() => setHoverRating(index + 1)}
          onMouseLeave={() => setHoverRating(0)}
        >
          ★
        </span>
      ))}
    </div>
  );
}

export default StarRating;

Here’s the breakdown of the changes:

  • We import the useRef hook.
  • We introduce a new state variable, hoverRating, initialized to 0. This variable will track the rating when the user hovers over the stars.
  • We add a ref to the span element to access the DOM element.
  • We update the color style to use hoverRating || rating. This means that if the user is hovering over a star, the color will be based on the hoverRating; otherwise, it will be based on the rating.
  • We add onMouseEnter and onMouseLeave event handlers to each star.
  • When the mouse enters a star, the setHoverRating function updates the hoverRating state to the index of the hovered star plus 1.
  • When the mouse leaves a star, the setHoverRating function resets the hoverRating state to 0.

Integrating the Component into Your Page

Now, let’s integrate the StarRating component into a page. Open the pages/index.js file (or your desired page) and modify it as follows:

import StarRating from '../components/StarRating';

function HomePage() {
  return (
    <div style={{ padding: '20px' }}>
      <h1>Star Rating Component Demo</h1>
      <p>Rate this article:</p>
      <StarRating totalStars={5} />
      <p>You can customize the number of stars!</p>
      <StarRating totalStars={7} />
    </div>
  );
}

export default HomePage;

Here’s what we’ve done:

  • We import the StarRating component.
  • We render the StarRating component inside a div element.
  • We pass the totalStars prop to customize the number of stars displayed.

Start your development server with npm run dev and navigate to http://localhost:3000 in your browser. You should see the star rating component displayed on the page. Try hovering over the stars and clicking them to see the interactive behavior.

Styling the Component (CSS-in-JS Approach)

While the basic functionality is in place, you might want to add more styling to the component to make it visually appealing. There are several ways to style a Next.js component. For simplicity, we’ll use a CSS-in-JS approach, which allows us to define styles directly within our JavaScript code. This is convenient for small projects and allows us to keep the styles close to the component code.

Let’s add some basic styling to the StarRating.js file:

import React, { useState } from 'react';

function StarRating({ totalStars = 5 }) {
  const [rating, setRating] = useState(0);
  const [hoverRating, setHoverRating] = useState(0);

  const starStyles = {
    cursor: 'pointer',
    fontSize: '2rem',
    color: 'gray',
    marginRight: '5px',
  };

  const filledStarStyles = {
    ...starStyles,
    color: 'gold',
  };

  return (
    <div>
      {Array(totalStars).fill(0).map((_, index) => (
        <span
          key={index}
          style={index < (hoverRating || rating) ? filledStarStyles : starStyles}
          onClick={() => setRating(index + 1)}
          onMouseEnter={() => setHoverRating(index + 1)}
          onMouseLeave={() => setHoverRating(0)}
        >
          ★
        </span>
      ))}
    </div>
  );
}

export default StarRating;

Here’s what we’ve added:

  • We define two style objects: starStyles for the default star appearance and filledStarStyles for the filled stars.
  • We use the spread operator (...) to inherit the properties from starStyles in filledStarStyles.
  • We apply the styles to the span element using the inline style attribute, conditionally applying filledStarStyles or starStyles based on the hover or rating state.
  • We added marginRight: '5px' to the starStyles object to provide spacing between the stars.

You can customize the styles further to match your website’s design. Experiment with different colors, sizes, and spacing to achieve the desired look and feel.

Common Mistakes and How to Fix Them

Here are some common mistakes and how to fix them:

  • Incorrect Import Path: Make sure the import path for the StarRating component is correct. Double-check that the file is in the correct directory. If you get an error like “Module not found,” verify the import statement.
  • Incorrect State Updates: Ensure that you’re correctly updating the rating and hoverRating states. Use the setRating and setHoverRating functions to update the state. Using direct assignment (e.g., rating = index + 1) will not trigger a re-render.
  • Missing Event Handlers: Make sure you’ve attached the onClick, onMouseEnter, and onMouseLeave event handlers to the star elements. Without these handlers, the component won’t be interactive.
  • Incorrect Styling: If the stars don’t look right, double-check your CSS styles. Make sure the font size, color, and spacing are set correctly. Use your browser’s developer tools to inspect the elements and debug the styles.
  • Prop Drilling: If you need to pass props through multiple levels of components, consider using React Context or a state management library like Redux or Zustand for more complex applications.

Key Takeaways

Here’s a summary of what you’ve learned:

  • You’ve built a fully functional, interactive star rating component using Next.js.
  • You’ve learned how to use the useState hook to manage component state.
  • You’ve implemented hover effects for a better user experience.
  • You’ve learned how to style the component using a CSS-in-JS approach.
  • You’ve learned how to integrate the component into a Next.js page.

FAQ

Here are some frequently asked questions:

  1. Can I customize the number of stars? Yes, you can customize the number of stars by passing the totalStars prop to the StarRating component.
  2. Can I use different star icons? Yes, you can replace the Unicode character (★) with any other icon or image.
  3. How can I store the user’s rating? You’ll need to send the rating data to your server and store it in your database. This typically involves making an API call when the user clicks a star.
  4. How do I handle partial star ratings? You can modify the component to calculate the rating based on the mouse position. You could use a half-star character (☆) and adjust the styling accordingly.
  5. Can I use this component with other frameworks? Yes, the core logic of the component can be adapted to other JavaScript frameworks like React, Vue, or Angular.

This tutorial has provided a solid foundation for building interactive components in Next.js. You can expand on this by adding features like persistence (saving the user’s rating), integrating with a backend, and implementing more advanced styling. The star rating component is a versatile tool that can significantly improve user engagement on your website or application. As you continue to build and refine your skills, remember that practice is key. Experiment with different features, styles, and approaches to create components that meet your specific needs. The world of web development is constantly evolving, so embrace the learning process, stay curious, and keep building!