How to toggle class in the nested component in ReactJS How to toggle class in the nested component in ReactJS reactjs reactjs

How to toggle class in the nested component in ReactJS


There are a couple ways you could handle this.

If you want the parent to control the additional class, you can simply pass it in to the child components and have them add it to their existing class name (JSFiddle demo):

var QuestionA = React.createClass({  render: function() {    return <section className={this.props.className + " question-a-container"}>Section A</section>;  }});var QuestionB = React.createClass({  render: function() {    return <section className={this.props.className + " question-b-container"}>Section B</section>;  }});var Root = React.createClass({  getInitialState: function() {    return { question: 'a' };  },  render: function() {    var qAclassName = this.state.question === 'a' ? 'active' : '';    var qBclassName = this.state.question === 'b' ? 'active' : '';    return (      <div className="question">              <QuestionA className={qAclassName} />        <QuestionB className={qBclassName} />        <div className="question-side-switcher" onClick={this.handleSideChanging}>Change</div>      </div>    );  },  handleSideChanging: function() {    this.setState({question: this.state.question === 'a' ? 'b' : 'a' });  }});

However, it probably makes more sense to let the child manage the class name, and simply send some data along to indicate if it should set its active class (JSFiddle demo):

// Using classSet to more easily create conditional class names;// see http://facebook.github.io/react/docs/class-name-manipulation.htmlvar cx = React.addons.classSet;var QuestionA = React.createClass({  render: function() {    // always set "question-a-container";    // set "active" if we got a truthy prop named `active`    var className = cx({      "question-a-container": true,      "active": this.props.active    });    return <section className={className}>Section A</section>;  }});var QuestionB = React.createClass({  render: function() {    // always set "question-b-container";    // set "active" if we got a truthy prop named `active`    var className = cx({      "question-b-container": true,      "active": this.props.active    });    return <section className={className}>Section B</section>;  }});var Root = React.createClass({  getInitialState: function() {    return { question: 'a' };  },  render: function() {    return (      <div className="question">        {/* For each question, compare to state to see if it's active. */}        <QuestionA active={this.state.question === 'a'} />        <QuestionB active={this.state.question === 'b'} />        <div className="question-side-switcher" onClick={this.handleSideChanging}>Change</div>      </div>    );  },  handleSideChanging: function() {    this.setState({question: this.state.question === 'a' ? 'b' : 'a' });  }});


As Brian Voelker mentioned it in the comments, the now official way to manipulate classes in React is to use the classnames utility.

You could define your two components like so:

import React, { Component } from 'react'import classNames from 'classnames'class QuestionA extends Component {  render () {    const { active } = this.props    const cx = classNames('question-a-container', { active })    return (      <section className={cx}></section>    )  }}

And simply pass them an active prop to toggle the namesake class.


I had a problem similar to this, I created a tabbed drawer and I was rendering only the component requested with the tabber but such solution was not ideal since I was losing the state of the child component everytime I switched to another one with the tabber.

To avoid this in the render I call a function to render all my childs, in this function I wrap each child in a div and I assign the needed className to the div, in my case I needed to display a single component per time so I was using display:block or none depending on the button clicked.

renderMyChilds() {        var renderedComponents = this.props.children.map(function(child, _key) {            if(this.state.drawerOpened == true) {                var ElementToRender = child;                var MyElement = (this.state.buttonSelected != _key) ? <div className="hiddenComponent"><ElementToRender /></div> : <div><ElementToRender /></div>;            } else {                var ElementToRender = child;                var MyElement = <div><ElementToRender className="hiddenComponent" /></div>;            }            return (MyElement);        }, this);        return renderedComponents;    }

.hiddenComponent { display: none; }

.visibleComponent { display: block; }