Reputation: 317
I have this Button A, with content "All categories". When I click this button, I want a div with content "show more" above Button A to display 6 other buttons, each consisting of "category 1", "category 2" up to 6. (and "show more" to disappear). Clicking any of these 6 buttons would hide the 6 buttons, and go back to being the "show more" div.
CODE
var React = require('react');
module.exports = React.createClass({
getInitialState: function() {
return ({
category: false,
selected: 'Total',
categories: [
{
name: 'Button 1',
id: 1,
},
{
name: 'Button 2',
id: 2,
},
{
name: 'Button 3',
id: 3,
},
{
name: 'Button 4',
id: 4,
},
{
name: 'Button 5',
id: 5,
},
{
name: 'Button 6',
id: 6,
}
]
})
},
selectCategory: function(event) {
(this.state.category) ? this.setState({category: false}) : this.setState({category: true})
},
render: function() {
if(this.state.category == true) {
var category = this.state.categories.map(function(category){
return (
<div
className="category-container"
onClick={this.selectCategory}>
<span> {category['name']} </span>
</div>
)
})
} else {
var category = (
<span id="showplease" onClick={this.selectCategory}> Show more </span>
)
}
console.log(this.state.selected)
return (
<div id="landing">
<div id="search-container">
<div id="category-selector-container">
{category}
<div id="selector" onClick={this.selectCategory}> Button A </div>
</div>
</div>
</div>
)
}
})
Simple enough. HERE IS MY ISSUE: Clicking any of the 6 buttons does not change the state, as if after being mapped, the individual components lost the 'onClick={this.selectCategory}' part. However, clicking the "Show more" div will run the selectCategory function, and will show the 6 buttons.
Any help? I can simply avoid the mapping and individually repeat the buttons, but I would like to know why this is not working.
Thank you in advance!
Upvotes: 0
Views: 960
Reputation: 24815
Your problem involves the this
variable. Whenever you create a new function
, a new context for this
is created and the old one is lost.
There are a few ways around this. A common one is to assign this
to a different variable, e.g. var self = this;
. Another way is to use bind
to ensure this
is passed from the outer scope. i.e.
var category = this.state.categories.map(function (category) {
return (
<div
className="category-container"
onClick={this.selectCategory}
>
<span>{category['name']}</span>
</div>
);
}.bind(this));
If you're using ES6, the best way is to use arrow functions, which automatically bind this
.
var category = this.state.categories.map((category) => (
<div
className="category-container"
onClick={this.selectCategory}
>
<span>{category['name']}</span>
</div>
));
Upvotes: 2