Reputation: 4502
In my case TopicList is a parent components and IndividualTopic is a child component. When user clicks on child component it changes the state of showTopicDescription to true. However, how do I pass value of showTopicDescription to parent component (TopicList) or directly set parent component state?
var TopicsList = React.createClass({
render: function () {
return (
<div className="row">
<IndividualTopic topic_no="1">
Topic 1
</IndividualTopic>
<IndividualTopic topic_no="2">
Topic 2
</IndividualTopic>
<IndividualTopic topic_no="3">
Topic 3
</IndividualTopic>
<IndividualTopic topic_no="4">
Topic 4
</IndividualTopic>
<div className="col-sm-12">
{ this.state.showTopicDescription ? <IndividualTopicPages /> : null }
</div>
</div>
);
}
});
var selected_topic_no;
var IndividualTopic = React.createClass({
getInitialState: function() {
return { showTopicDescription: false };
},
onClick: function() {
this.setState({ showTopicDescription: true });
selected_topic_no = this.props.topic_no - 1;
},
render: function () {
return (
<div>
<div className="col-sm-2">
<div onClick={this.onClick} className="single-topic" data-topic-no={this.props.topic_no}>
{this.props.children}
</div>
</div>
</div>
);
}
});
Upvotes: 1
Views: 1202
Reputation: 1840
Here's a commented up version based on my comment.
I've added a bunch of comments, feel free to ask any more questions, the main point I was trying to get across is that the IndividualTopic component should be dumb and have very little logic inside it, just get passed props and call callbacks.
This is thoroughly untested pseudo-code, please don't expect it to work as is - I'm just trying to illustrate an approach.
var TopicsList = React.createClass({
// setup our generic callback method to handle all topic selection
// this gets passed the event object and topic ID and sets the state
topicSelectionCallback: function(topicID, event) {
this.setState({
showTopicDescriptions: true,
selectedTopicID: topicID
});
},
// maybe you need to close the topic as well...
closeTopicCallback() {
this.setState({
showTopicDescription: false
});
}
render: function () {
return (
<div className="row">
// I've neatened up your syntax for the IndividualTopic elements
// props should be camel case and one their own line, I pass
// through the callback as well as the label
<IndividualTopic
topicID="1"
selectionCallback={this.topicSelectionCallback}
label="Topic"
>
<IndividualTopic
topicID="2"
selectionCallback={this.topicSelectionCallback}
label="Topic"
>
<IndividualTopic
topicID="3"
selectionCallback={this.topicSelectionCallback}
label="Topic"
>
<IndividualTopic
topicID="4"
selectionCallback={this.topicSelectionCallback}
label="Topic"
>
<div className="col-sm-12">
{ this.state.showTopicDescription ?
// pass the selected topic ID assuming this component will
// then re-render based on the ID that it's passed
<IndividualTopicPages
selectedTopic={this.state.selectedTopicID}
closeTopicCallback={this.closeTopicCallback} // closing the topic
/>
: null }
</div>
</div>
);
}
});
// this doesn't really need to be a var in this scope
// var selected_topic_no;
var IndividualTopic = React.createClass({
onClick: function(event) {
// assuming you're using ES6, declare this as a let as it's only
// ever used here, if not just a local var will work fine
let selectedTopicID = this.props.topicID - 1;
// call the callback that's passes as a prop, send the topic ID
// as a parameter
this.props.topicSelectionCallback(event, selectedTopicID);
},
render: function () {
return (
<div>
<div className="col-sm-2">
<div onClick={this.onClick} className="single-topic" data-topic-id={this.props.topicID}>
{this.props.label} {this.props.topicID} // render out the label and topicID here
</div>
</div>
</div>
);
}
});
Upvotes: 0
Reputation: 768
From the click handler of IndividualTopic call the setTopicDescription function on the parent component using this.props
which we registered in the render method of parent component.Refer below code -
var TopicsList = React.createClass({
setTopicDescription: function(topicDescription){
//HERE WE GET THE TOPIC DESCRIPTION FLAG. CHEEERS WE CAN DO WHAT WE NEED OVER HERE
},
render: function () {
return (
<div className="row">
<IndividualTopic topic_no="1" setTopicDescription={this.setTopicDescription} >
Topic 1
</IndividualTopic>
<IndividualTopic topic_no="2" setTopicDescription={this.setTopicDescription}>
Topic 2
</IndividualTopic>
<IndividualTopic topic_no="3" setTopicDescription={this.setTopicDescription}>
Topic 3
</IndividualTopic>
<IndividualTopic topic_no="4" setTopicDescription={this.setTopicDescription}>
Topic 4
</IndividualTopic>
<div className="col-sm-12">
{ this.state.showTopicDescription ? <IndividualTopicPages /> : null }
</div>
</div>
);
}
});
var selected_topic_no;
var IndividualTopic = React.createClass({
getInitialState: function() {
return { showTopicDescription: false };
},
onClick: function() {
this.setState({ showTopicDescription: true });
selected_topic_no = this.props.topic_no - 1;
this.props.setTopicDescription({ showTopicDescription: true });
},
render: function () {
return (
<div>
<div className="col-sm-2">
<div onClick={this.onClick} className="single-topic" data-topic-no={this.props.topic_no}>
{this.props.children}
</div>
</div>
</div>
);
}
});
Upvotes: 2