I have 4 boxes with component name SingleTopicBox
. I would like to change color of box when user clicks on particular box. SingleTopicBox
component has props topicID as a unique identifier for each box. Currently when user clicks on any of the box it's changing state of all the boxes bgDisplayColor: 'red'
however, I would like to only change the color of boxes that is clicked.
index.jsx
import {React, ReactDOM} from '../../../../build/react';
import SelectedTopicPage from './selected-topic-page.jsx';
import TopicsList from './topic-list.jsx';
import topicPageData from '../../../content/json/topic-page-data.js';
export default class MultiTopicsModuleIndex extends React.Component {
constructor(props) {
super(props);
this.setTopicClicked = this.setTopicClicked.bind(this);
this.onClick = this.onClick.bind(this);
() => topicPageData;
this.state = {
isTopicClicked: false,
bgDisplayColor: 'blue'
};
};
onClick(topicID) {
this.setState({isTopicClicked: true, topicsID: topicID, bgDisplayColor: 'red'});
};
setTopicClicked(boolean) {
this.setState({isTopicClicked: boolean});
};
render() {
return (
<div className="row">
{this.state.isTopicClicked
? <SelectedTopicPage topicsVisited={this.topicsVisited} setTopicClicked={this.setTopicClicked} topicsID={this.state.topicsID} key={this.state.topicsID} topicPageData={topicPageData}/>
: <TopicsList bgDisplayColor={this.state.bgDisplayColor} topicsVisited={this.topicsVisited} onClick={this.onClick}/>}
</div>
);
}
};
topic-list.jsx
import {React, ReactDOM} from '../../../../build/react';
import SingleTopicBox from './single-topic-box.jsx';
import SelectedTopicPage from './selected-topic-page.jsx';
export default class TopicsList extends React.Component {
render() {
return (
<div className="row topic-list">
<SingleTopicBox bgDisplayColor={this.props.bgDisplayColor} topicID="1" onClick={this.props.onClick} label="Topic"/>
<SingleTopicBox bgDisplayColor={this.props.bgDisplayColor} topicID="2" onClick={this.props.onClick} label="Topic"/>
<SingleTopicBox bgDisplayColor={this.props.bgDisplayColor} topicID="3" onClick={this.props.onClick} label="Topic"/>
<SingleTopicBox bgDisplayColor={this.props.bgDisplayColor} topicID="4" onClick={this.props.onClick} label="Topic"/>
</div>
);
}
};
Single-topic-box.jsx
import {React, ReactDOM} from '../../../../build/react';
export default class SingleTopicBox extends React.Component {
render() {
var divStyle = {
backgroundColor: this.props.bgDisplayColor
};
return (
<div>
<div className="col-sm-2">
<div style={divStyle} className="single-topic" data-topic-id={this.props.topicID} onClick={() => this.props.onClick(this.props.topicID)}>
{this.props.label}
{this.props.topicID}
</div>
</div>
</div>
);
}
};
You can't seem to decide whether you want the state for the top-level component or the SingleTopicBox, but you put it in the top-level component anyway.
You should make a choice: Should the SingleTopicBox component know it's been clicked or should MultiTopicsModuleIndex remember which SingleTopicBox has been clicked?
If you are ok with multiple SingleTopicBox component having the clicked state at the same time, you should move the state and the onClick hander to SingleTopicBox. You don't need to remember both if the component has been clicked and its background color. For example, you can:
getInitialState: function() {
return {
bgDisplayColor: 'blue'
};
},
onClick() {
this.setState({bgDisplayColor: 'red'});
};
then use this.state.bgDisplayColor
in the render method
If you want only one component to be clicked at any single time, so that previously clicked component goes back to unclicked when another one is clicked, you may want to have the state and the handler live in the top-level component, as you already have it in your code. The only thing you need to remember in the state is topicID, then you pass it to the TopicsList component as property like this:
<TopicsList clickedTopicID={this.state.topicID} onClick={this.onClick} />
and in TopicsList you render something like this:
render: function() {
var topics = [
{id: 1, label: 'Topic'},
{id: 2, label: 'Topic'},
{id: 3, label: 'Topic'},
{id: 4, label: 'Topic'},
];
var boxes = [];
for (var i = 0, len = topics.length; i < len; i++)
boxes.push(<SingleTopicBox
bgDisplayColor={(this.props.clickedTopicID == topics[i].id) ? 'red' : 'blue'}
topicID={topics[i].id}
onClick={this.props.onClick}
label={topics[i].label}
/>);
return (
<div className="row topic-list">
{boxes}
</div>
);
}
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