AngularJS has ng-class for conditionally applying classes. This is a replacement for that in React.
At accelo we are in the process of transitioning from AngularJS to React. We are not using a CSS-in-JS library, where you might have your conditional styling in the Javascript itself and have no need for this utility.
This is framework agnostic so it can be used in Vue (etc) despite the click-bait title of this article.
This replacement allows you to do the following (the classes use BEM syntax).
// React functional component
import { getActiveClasses } from "get-active-classes"
const MenuItemFocus = ({
orientation,
forceActive,
withTransition,
className,
}) => (
<div
className={getActiveClasses("menuItemFocus", className, {
"menuItemFocus--vertical": orientation === "vertical",
"menuItemFocus--horizontal": orientation === "horizontal",
"menuItemFocus--active": forceActive,
"menuItemFocus--withTransition": withTransition,
})}
></div>
)
So if the component had the props of
<MenuItemFocus
orientation="vertical"
forceActive={true}
withTransition={false}
className="widthFull"
/>
the resulting HTML will be
<div
class="menuItemFocus widthFull menuItemFocus--vertical menuItemFocus--active"
></div>
Here is the code for the getActiveClasses function. It's written in typescript, but you can strip that out if you need to use it in a regular JS environment.
type ConditionalClasses = { [key: string]: any }
type Option = ConditionalClasses | string
export function getActiveClasses(...classes: Option[]): string {
return [].concat(...classes).reduce((result, option: Option) => {
const nextClasses =
typeof option === "object" ? joinClasses(option) : option
return `${result}${result ? " " : ""}${nextClasses}`
}, "")
}
function joinClasses(classes: ConditionalClasses) {
return Object.keys(classes)
.filter(key => classes[key])
.join(" ")
}
There is also a packaged version of this utility if you don't need to modify it at all.
yarn add get-active-classes
Next up I'm thinking about performance with this utility in React. For example, caching the output if the input is the same to improve performance on additional renders. When I run into a case where I think the performance might an issue ill give that a go and update this blog post! (and package).