blog post

Conditional Class Rendering in React using CLSX

When developing React applications, managing conditional class names can quickly become cumbersome, especially as components grow in complexity. Traditionally, developers concatenate strings and use conditional logic to handle these cases, which can lead to error-prone and hard-to-read code. In this blog post, we'll explore how the clsx library offers a cleaner, more efficient solution to this common problem, providing examples to demonstrate its advantages.

How to Conditionally Apply CSS Classes - Manual Approach

We are going to explore a Button React component that has a single prop that indicates whether the button is active. The traditional method of appending classes conditionally in React is achieved by manually writing classes concatenations:

jsx
const Button = ({ isActive, children }) => { let buttonClass = "btn"; if (isActive) { buttonClass += " btn-active"; } return <button className={buttonClass}>{children}</button>; }

When a button needs to be active - a btn-active css class is applied that make changes to the button's background color.

Let's define 2 buttons and see how they differ:

jsx
<div> <Button isActive={false}> Register </Button> <Button isActive={true}> Subscribe </Button> </div>

Screenshot_1

Now let's explore a more complex Button component that have several states like primary, danger, or disabled:

jsx
const ComplexButton = ({ primary, danger, disabled, children }) => { let buttonClass = "btn"; if (primary) { buttonClass += " btn-primary"; } if (danger) { buttonClass += " btn-danger"; } if (disabled) { buttonClass += " btn-disabled"; } return ( <button className={buttonClass}> {children} </button> ); }

Let me explain what we are doing here: we start with a base class btn and append additional classes based on whether the button is primary, danger or disabled. This modifies the styling to show different borders and background colors for the button.

Primary button - is a main button on the current screen and should be visually distinguished from other buttons, for example a save button.

Danger button - is a button that indicates a possible risky action, like rejecting the updated data.

Screenshot_2

As you can see, even for moderately complex conditions, the class string handling becomes verbose and harder to read. And we need so much code to write.

Manual string concatenation is susceptible to errors, such as missing spaces between class names or misplacing condition checks. As more conditions are added, the approach becomes difficult to maintain.

How to Conditionally Apply CSS Classes - Using CLSX Library

In such use cases clsx library comes to the rescue. clsx is a tiny library designed to make conditional class rendering in React (and beyond) much simpler and more readable. It allows you to write expressions that are easier to maintain and understand.

Here's how you can refactor the first example of a Button component using clsx library:

jsx
import clsx from 'clsx'; const Button = ({ isActive }) => { return <button className={clsx("btn", { "btn-active": isActive })}>Register</button>; }

clsx accepts multiple arguments and merges them intelligently. Arguments can be strings, objects, or arrays, providing great flexibility.

With a help of clsx library you can have a pretty simple and easy to read code even for a complex Button component:

jsx
import clsx from 'clsx'; const ComplexButton = ({ primary, danger, disabled, children }) => { return ( <button className={clsx("btn", { "btn-primary": primary, "btn-danger": danger, "btn-disabled": disabled })} > {children} </button> ); }

More Examples of Using CLSX Library

We'll build a UserProfile component that displays different styles based on the user's status, such as whether they are online, whether their subscription is active and what role they have.

First, let's write this manually:

jsx
const UserProfile = ({ user }) => { let avatarClass = "avatar"; let nameClass = "username"; if (user.isOnline) { avatarClass += " avatar-online"; } if (user.role === "admin") { avatarClass += " avatar-admin"; } else if (user.role === "moderator") { avatarClass += " avatar-moderator"; } if (user.isSubscriber) { nameClass += " username-highlighted"; } return ( <div className="user-profile"> <h1 className={nameClass}>{user.name}</h1> <ProfileIcon className={avatarClass} /> </div> ); }

Let me explain what we are doing here:

  1. We start with a base class avatar and append additional classes based on whether the user is online or what role he has. This modifies the styling to show different borders and colors for the avatar.
  2. The base class for the user's name is username, and if the user is a subscriber, we add a highlighted style to make it stand out.

Let's show a few users:

jsx
<div> <UserProfile name={"Anton"} isSubscriber={true} role={"admin"} isOnline={true} /> <UserProfile name={"John"} isSubscriber={true} role={"moderator"} isOnline={true} /> <UserProfile name={"Nick"} isSubscriber={true} role={""} isOnline={false} /> <UserProfile name={"Tim"} isSubscriber={false} role={""} isOnline={false} /> </div>

Screenshot_3

And here is a much better version when using clsx library:

jsx
import clsx from "clsx"; const UserProfile = ({ user }) => { const avatarClasses = clsx("avatar", { "avatar-online": user.isOnline, "avatar-admin": user.role === "admin", "avatar-moderator": user.role === "moderator" }); const nameClasses = clsx("username", { "username-highlighted": user.isSubscriber }); return ( <div className="user-profile"> <h1 className={nameClasses}>{user.name}</h1> <ProfileIcon className={avatarClasses} /> </div> ); }

Nuances When Using CLSX Library

  1. The clsx function can take any number of arguments, that can be either: string, boolean, array or object.
  2. Any false type of values are discarded, for example:
js
// This returns empty string "" clsx(true, false, 0, "", null, undefined, NaN);
  1. There are 2 versions of clsx library: original (239 bytes) and lite (140 bytes). The lite has the same API as original but accepts only string arguments.

Summary

clsx library offers a more elegant solution for handling conditional class names in React, enhancing code readability and maintainability. It allows developers to more easily manage multiple conditional classes without the boilerplate of manual string concatenation, clsx makes your React components cleaner and less prone to bugs.

Hope you find this blog post useful. Happy coding!

After reading the post consider the following:

  • Subscribe to receive newsletters with the latest blog posts

  • Download the source code for this post from my github (available for my sponsors on BuyMeACoffee and Patreon)

If you like my content - consider supporting me

Unlock exclusive access to the source code from the blog posts by joining my Patreon and Buy Me A Coffee communities!