10

Suppose I have a ReactElement that has a className, and I want to add a new class to its className, without overriding the existing className. How am I supposed to do this?

I've tried the following but it does override the existing className:

var hello = <Hello name="World" className="base"/>;
hello = React.cloneElement(hello,{className: "text1"});
hello = React.cloneElement(hello,{className: "text2"});

However this solution works:

var hello2 = <Hello name="World" className="base"/>;
hello2 = React.cloneElement(hello2,{className: hello2.props.className + " test1"});
hello2 = React.cloneElement(hello2,{className: hello2.props.className + " test2"});

But is this safe to use ReactElement.props like that? Is it part of the public API of a ReactElement and is supposed to be kept retrocompatible in the future? I was not able to find this in the documentation.

Is there another way to achieve this?

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
  • Use a shared variable instead? :P I think it's a reasonably safe bet that ReactElement will have props on it in the future though – Dominic Oct 30 '15 at 11:57

2 Answers2

19

The structure of React elements is stable, see Nodes and Elements, so your approach is completely safe (and recommended).

If you do a lot of className manipulation, I recommend using the classnames module.

Your previous example would then become:

var cx = require('classnames');

React.cloneElement(hello2, {
  className: cx(hello2.props.className, "test1"),
});
Alexandre Kirszenberg
  • 35,938
  • 10
  • 88
  • 72
-6

CloneElement is slow and seems like overkill. Can you use a mixin to do this and npm classnames package (https://www.npmjs.com/package/classnames). Along the lines of

var classNames = require('classnames');

a function to add the class strings or convert into an object (see below) to hand off to classNames as in the docs

classNames('foo', 'bar'); // => 'foo bar'

classNames({ foo: true }, { bar: false }); // => 'foo'

Davet
  • 334
  • 1
  • 3
  • 15
  • 3
    is this supposed to be an answer? or is it another question? – Maslow Dec 06 '16 at 12:53
  • Its a suggestion of an alternative way of doing it not a question - do you have anything constructive to actually say ? – Davet Jan 06 '17 at 14:10
  • 3
    asking if this is an answer is a legitimate question. Asking a question or commenting in an answer, which is what it seemed to me this is, is not helpful. Did you mean to say `If you can use a mixin and the npm classnames package then you can do this: ...` ? – Maslow Jan 06 '17 at 14:14