ReactHustle

How to Implement Multiple Classnames in NextJS

Jasser Mark Arioste

Jasser Mark Arioste

How to Implement Multiple Classnames in NextJS

Hello, hustlers! In this tutorial, you'll learn the best practice to implement multiple classnames in React or NextJS.

The Problem #

If you're using multiple classNames to style your components in React, things can go ugly really quickly. Especially if you have to use conditional classNames. In this tutorial, we'll explore how to implement multiple conditional classNames in React or NextJS.

Ways to Implement Multiple Classnames #

Here are the ways to implement multiple classNames that I know of:

  1. Using string interpolation or concatenation
  2. Using utility packages like classnames and clsx to handle toggling of classes. I recommend using this approach

Using String Interpolation or Concatenation #

As a beginner, this is what we usually do at first. But you'll soon realize that it becomes very hard to maintain and the code will be less readable. If you're using TailwindCSS for styling, the problem becomes exponentially apparent.

Here's an example: 

import React, { ComponentPropsWithRef } from "react";

type Props = ComponentPropsWithRef<"button">;

const MyButton = (props: Props) => {
  const disabledClass = props.disabled
    ? "disabled opacity-60 pointer-events-none"
    : "";
  const hoverClass = "hover:bg-indigo-700";
  return (
    <button
      {...props}
      className={`${disabledClass} ${hoverClass} bg-indigo-500 text-indigo-50 p-2`}
    />
  );
};

export default MyButton;
123456789101112131415161718

As you can see, the more you use string interpolation, the less readable the code becomes. if you want to see what the value of thedisabledClass constant is, you have to scroll up to see the code. In other words,  you don't have the whole class list at a glance. This becomes more apparent in production-grade applications where there are a lot of component states to take care of.

Next, we'll use utility packages to make our lives easier:

Using Utility Packages #

Currently, there are two utility packages that solve the problem above: classnames and clsx. They don't have any difference aside from clsx being a bit smaller than classnames. Both packages are less than 500 bytes in size so it doesn't matter what you choose. Just a preference to see which package name sounds more cool.

First, we have to install the package, you can choose either one:

yarn add clsx
# or
yarn add classnames

Now let's refactor our code.

Using classnames package: #

import cn from "classnames";
import React, { ComponentPropsWithRef } from "react";

type Props = ComponentPropsWithRef<"button">;

const MyButton = (props: Props) => {
  return (
    <button
      {...props}
      className={cn({
        "hover:bg-indigo-700": true,
        "bg-indigo-500 text-indigo-50 p-2": true,
        "disabled opacity-60 pointer-events-none": props.disabled,
      })}
    />
  );
};

export default MyButton;
12345678910111213141516171819

Now, we can see all the classes used by the component without scrolling up.

In line 10, we use the cn function and pass an object where the keys are the classes that we want to toggle, and the values are boolean values that may or may not be based on the component's state.

In line 11, the "hover:bg-indigo-700" class will always be rendered since its value is always true. However, on line 13, the "disabled opacity-60 pointer-events-none" will only be rendered if props.disabled is true.

Here's the output:

// <MyButton/>
<button class="hover:bg-indigo-700 bg-indigo-500 text-indigo-50 p-2"/>

// <MyButton disabled/>
<button disabled="" class="hover:bg-indigo-700 bg-indigo-500 text-indigo-50 p-2 disabled opacity-60 pointer-events-none"/>
12345

Using clsx package: #

Using clsx package is pretty much the same as the classnames package. We just need to change a couple of lines:

import clsx from "clsx";
import React, { ComponentPropsWithRef } from "react";

type Props = ComponentPropsWithRef<"button">;

const MyButton = (props: Props) => {
  return (
    //
    <button
      {...props}
      className={clsx({
        "hover:bg-indigo-700": true,
        "bg-indigo-500 text-indigo-50 p-2": true,
        "disabled opacity-60 pointer-events-none": props.disabled,
      })}
    />
  );
};

export default MyButton;
1234567891011121314151617181920

Conclusion #

You learned how to implement multiple class names in NextJS so that it will be more maintainable, readable, and more importantly production-grade.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.

Other Alternative Packages #

There's one other package that's available which is classcat

Resources #

  1. classnames and clsx npm page

Credits: Image by Matt Hardy from Pixabay

Share this post!

Related Posts

Disclaimer

This content may contain links to products, software and services. Please assume all such links are affiliate links which may result in my earning commissions and fees.
As an Amazon Associate, I earn from qualifying purchases. This means that whenever you buy a product on Amazon from a link on our site, we receive a small percentage of its price at no extra cost to you. This helps us continue to provide valuable content and reviews to you. Thank you for your support!
Donate to ReactHustle