loading...

Simple `classnames` and small libraries

greduan profile image Eduardo Lavaque Updated on ・2 min read

Thought I'd share my thoughts on small libraries like classnames which are very used helpers, but could often be dropped in exchange for a homegrown alternative.

Here's a tiny classnames implementation with only the most basic features:

export default (...classes) => {
  const result = []
  classes.forEach(a => {
    if (typeof a === 'string') {
      result.push(a);
    } else if (Object.prototype.toString.call(a) === '[object Object]') {
      Object.keys(a).forEach(b => a[b] && result.push(b))
    }
  })
  return result.join(' ')
}

This works. I tested it. (Famous last words.)

Why was I prompted to write this? Just as an exercise. But also because I distinctly remember having a bad impression about how long the code of the library was, even though I check it now and in actuality it's very small.

But writing this put a bit into perspective into how much I'm giving up of the control of my code and its behaviour by giving the simple simple work to an external library, that perhaps could've been written in one minute like the one above.

If something doesn't work I have to check out the source, but first I've to double check which version I'm using and check its source code, not of newer or older versions, and then I've to read it. And it's in my node_modules so to add a console.log to it I've to edit the node_modules file. Or at least that's how I do it.

In comparison I can just go to the utils/classnames.js file and read it, simple enough, put debugger statements or console.logs or whatever. Easy.


BTW, instead of a fancy function like the above, you could actually just follow a pattern similar to the following:

const trimClassName = (class) => class.replace(/\s{2,}/g, ' ');

const Foo = () => (
  <div
    className={trimClassName(`
      xyz
      ${someTruth() ? 'truth' : 'notruth'}
      ${someFalsety() ? 'false' : ''}
    `)}
  >
    Hello world
  </div>
);

So I just completely skipped a complex function and I just ran a search and replace for two-or-more whitespaces replacing them with one whitespace, on a string which uses built-in JS string templating.

Or another approach:

const cx = (...classes) => classes.filter(a => !!a).join(' ')

const Foo = () => (
  <div
    className={cx(
      'xyz',
      someTruth() ? 'truth' : 'notruth',
      someFalsety() && 'false'
    )}
  >
    Hello world
  </div>
);

Now all that said. I realize homegrown options are not always the most performant options, but I prefer to leave the micro optimizations to the engine, and I like to work on macro optimizations.

Let me know your thoughts, often people I talk to prefer to use a library because "somebody already wrote it, no need to write it ourselves", but in some places I disagree with this.

Discussion

markdown guide
 

This is the question of software development. What are the tradeoffs between doing it yourself and relying on a dependency.