Something short and sweet: let's explore one of the better ways to write conditional classes in React. I will use a simple menu item functional component and some pseudocode.
const MenuItem = ({ children }) => {
// TODO: add classes when a menu item is "active"
// TODO: optionally add classes for dark theme
return (
<li className="menu-item">
{children}
</li>
);
};
First attempt: Logical && operator
const MenuItem = ({ children }) => {
return (
<li className={`menu-item ${isActive && 'menu-item-active'}`}>
{children}
</li>
);
};
Cons: This code actually has a hidden bug. For falsy values the false
css class appears in the DOM. Let's get rid of the bug in our next attempt.
Second attempt: Ternary operator
const MenuItem = ({ children }) => {
return (
<li className={`menu-item ${isActive ? 'menu-item-active' : ''}`}>
{children}
</li>
);
};
Cons: This code does not have any hidden bugs like before, but looks too complex for such a simple task. It is also not so readable as it should be and can get event worse: imagine having other use conditions like isDarkTheme
.
Third attempt: Constructing className strings
The third attempt and my personal favorite is using a function (npm package) to construct the className. It is actually a mix of the first 2 attempts:
const MenuItem = ({ href, children }) => {
return (
<li className={classnames(
'menu-item',
isActive && 'menu-item-active',
isDarkTheme && 'menu-item-dark'
)}>
{children}
</li>
);
};
NPM packages
Here is a list of NPM packages and their bundle sizes. They all have the same implementations, so you can choose which one suits you best:
- classnames with a tiny 729 bytes
- clsx with a tiny 516 bytes
- merge-class-names at an incredibly tiny 372 bytes
Conclusion
We as developers always read more code than we write. That's why I always choose to write code that is more readable and easily understandable by anyone.
Top comments (0)