Nitsorn Wongsajjathiti
Nitsorn Wongsajjathiti

Reputation: 317

Calling a function from a conditional variable - ReactJS

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

Answers (1)

David L. Walsh
David L. Walsh

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

Related Questions