I have such render() method in my root component:
render: function() {
return (
<div className="question">
<QuestionA question={this.props.question} author={this.props.author}/>
<QuestionB yes={this.state.yes} no={this.state.no} />
<div className="question-side-switcher" onClick={this.handleSideChanging}></div>
</div>
);
}
Where I want to toggle the 'active' class between QuestionA and QuestionB components when user clicked the button. How can I do this? Keep in mind, that QuestionA and QuestionB are set their own classNames in their render() methods. For example QuestionB's render():
render: function() {
return (
<section className="question-b-container">
...
</section>
);
}
To toggle class on click with React, we can set the className prop. to create the MyComponent component. In it, we have the isActive state. We set it with the setActive function in the toggleClass function.
Replace the contents of src/ToggleSwitch/ToggleSwitch. js with the following: import React from "react"; import PropTypes from "prop-types"; import './ToggleSwitch. scss'; /* Toggle Switch Component Note: id, checked and onChange are required for ToggleSwitch component to function.
A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.
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.html
var 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With