MuTasim

cx.

Sometimes, we don't need to import an entire library just to utilize a specific function. In my case, it was the clsx and classnames npm package. Upon revisiting some of my projects, I realized I only used the cx (or classnames) function from there. But then, a thought struck me—what if I create my own function? This would result in fewer dependencies for my project. Hence, I came up with this concise 4-line code snippet:

./lib/utils.js
type ClassNamesArg = string | { [key: string]: boolean };

export const cx = (...classNames: ClassNamesArg[]): string => {
    return classNames
        .flatMap((arg) => (typeof arg === 'string' ? arg : Object.entries(arg).filter(([_, value]) => value).map(([key]) => key)))
        .join(' ');
};

This code snippet not only solved my problem but also reduced the dependency count in my project by one. Now, let's delve into how I use it.

How does it work?

The cx function employs flatMap to transform each argument into an array of strings. If an argument is a string, it remains unchanged; if it's an object, the function extracts keys with truthy values. Instead of the conventional approach of mapping and then flattening, I opted for flatMap, as it is recommended and widely supported across all browsers.

Usage:

page.tsx
import { cx } from "@/lib/utils";

export default function Home({ isActive, hasError, styles }) {
    const containerClasses = cx(
        'bg-blue-500',                      // Default class
        { 'text-white': isActive },        // Conditional class based on the isActive prop
        { 'border-red-500': hasError },   // Conditional class based on the hasError prop
        ...styles                        // Additional classes passed as an array or string
    );

    return (
        <div className={containerClasses}>
            <p>This is my Home Page</p>
        </div>
    )
};

In practice, it's a commendable practice to keep dependencies as minimal as possible. Sometimes, without paying attention, we end up with an abundance of dependencies, resulting in a substantial npm module size. If there are small functions or custom hooks that we can implement ourselves, potentially yielding more efficiency, there's no need to import them.

So, keep your codebase lean and efficient, steering clear of unnecessary dependencies!