Merging two or more className could be a troublesome text processing. For instance, if you are not used to JavaScript’s undefined, and are not careful enough, you could end up embedding an unexpected “undefined” class without knowing.

function Foo({ className }: { className?: string }) {
  return <div className={`default-class ${className}`}>foo</div>
}
// <Foo /> will be rendered as <div class="default-class undefined">foo</div>

It can be avoided by setting its default value as an empty string, but still, there’s another minor problem. When the className parameter is omitted, the class will contain unnecessary trailing whitespaces like "default-class ". It doesn’t seem so harmful but no one needs it.

function Foo({ className = "" }: { className?: string }) {
  return <div className={`default-class ${className}`}>foo</div>
}
// <Foo /> will be rendered as <div class="default-class ">foo</div>
// with trailing whitespace :/

Writing a piece of code to solve it is not quite difficult but there’s already a great helper method to deal with manipulating className. classnames provides a simple interface to craft a className string. It receives variable length args and simply ignores any falsy value. The problems above can be solved by just passing original values into classnames.

import classnames from "classnames"

function Foo({ className = "" }: { className?: string }) {
  return <div className={classnames("default-class",  className)}>foo</div>
}
// <Foo /> will be rendered as <div class="default-class">foo</div>

Not only that, the function provides various ways to express dynamic class name lists. It’s handy and you’d better use it before considering DIY.

See Also