Feature Request: className as object or array (vue-alike)

This issue has been tracked since 2022-09-13.

I would like to propose support for vue-alike classes, in which instead of accepting only string, it would also accept array or objects.

This support greatly improves code maintainability by avoiding the use of join functions. Also, production performance can be reduced to zero if the code is optimized for the current supported format.

Currently React only allows strings like className, so we can have something like:

<div className="active">

If we want something dynamic, we need to define something like:

const isActive = true;

<div className={ isActive ? 'active' : '' }>

But if we need more than one piece of information, things start to get complicated, but nothing absurd:

const isActive = false,
      isSortable = true;

<div className={ (isActive ? 'active' : '') + (isSortable ? '<space>sortable' : '') }>

A definition with more optional classes could make the code a little more complicated to handle. So allowing support for objects like vue allows greatly improves code quality:

const isActive = false,
      isSortable = true;

<div className={ { active: isActive, sortable: isSortable } }>

Even better, if the name of the class is the same as the name of the variable that stores it, we can reduce this even further:

const active = false,
      sortable = true;

<div className={ { active, sortable } }>

It is also possible to use arrays in various ways, for example by applying various classes as they exist in an array:

const fruits = [ 'banana', 'apple' ];

<div className={ fruits }>

I don't particularly use as above, however, it's common to merge arrays with objects like this:

<div className={ [ 'item', { active, sortable } ] }>

One or several functions can be used during the union:

const isActive = () => [ 'active ' ];
const isSortable= () => user.exists ? [ 'sortable' ] : null;

<div className={ [ 'item', isActive, isSortable ] }>
rentalhost wrote this answer on 2022-09-13

There are libs that do just that, but I'd really like this to be something native:
https://github.com/JedWatson/classnames

FrameMuse wrote this answer on 2022-09-16

I think this could be inappropriate for React itself, because it doesn't transform any passed values, so your example shows that React will transform [ 'item', { active, sortable } ] to "item active sortable".

The transformation needs to be applied in every render, when in most projects the classnames are already maintained by their on way.

You suggested the library that is doing just that, so why do you want this breaking change to be native, if there is already a nice existing solution?

Also, you could create your own React Component to do exactly this - this is what React magic is.

rentalhost wrote this answer on 2022-09-17

@FrameMuse I don't think it's a problem for React to transform data, as long as there isn't a regression to its original and raw functionality. Or, at least, if it were possible to implement a plugin that could perform this transformation "almost natively". But I understand that this can be part of the "React philosophy".

There is also no breaking change, as className can only take a string as a parameter currently. And the suggested functionality would only expand its capacity to support array and object.

I can't imagine how I could make a React Component that does this, I'm currently using the classnames lib (from my previous comment) and it works fine, on the other hand, I always need to remember to import it. Something like: className={classnames({ active, visible })}.

FrameMuse wrote this answer on 2022-09-17

@rentalhost Yes, I was talking about "React philosophy". After some rethinking, there is actually no breaking changes. If you don't want to care about importing anything manually, just use an extension for your IDE so it does that for you.

And this is how you can create your own "React Component" with className transforming.

interface DivProps extends Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "className"> {
  className?: unknown[]
}

function Div(props: DivProps) {
  const className: string = YOUR_CLASSNAME_TRANSFORM(props.className)
  
  return (
    <div {...props} className={className} />
  )
}
More Details About Repo
Owner Name facebook
Repo Name react
Full Name facebook/react
Language JavaScript
Created Date 2013-05-24
Updated Date 2022-10-03
Star Count 195549
Watcher Count 6650
Fork Count 40505
Issue Count 1119

YOU MAY BE INTERESTED

Issue Title Created Date Updated Date