OnClick Not Working React Js

I am trying to call a function when a user clicks a div (using onClick in react). I don't need to pass any arguments at this moment, just need to call the function. I'm fairly new to react.js so apologies in advance for my ignorance. Thanks.

var Test = React.createClass({

btnTapped: function(){
    console.log('tapped!');
},
render: function() {
    var stationComponents = this.props.stations.map(function(station, index) {

    return <div onClick={btnTapped()}><img src="img/test.png" />{station}</div>;

    });
    return <div>{stationComponents}</div>;
   }
});

var cards = ["amazon", "aeo", "aerie", "barnes", "bloomingdales", "bbw","bestbuy", "regal", "cvs", "ebay", "gyft", "itunes", "jcp", "panera", "staples", "walmart", "target", "sephora", "walgreens", "starbucks"];

ReactDOM.render(<Test stations={cards} />, document.getElementById('test-div'));
2

11 Answers

If your build system has support for babel, Use ES6 arrow functions in your react code.

If you are using ES6 class for creating components, use method binding at the constructor level to avoid binding at every render call and also provide a key to the div tag inside the map function.

class Test extends React.Component {
    constructor(props) {
        super(props);
        this.btnTapped = this
            .btnTapped
            .bind(this);
    }
    btnTapped() {
        console.log('tapped');
    }
    render() {

        return (
            <div>
                {this
                    .props
                    .stations
                    .map((station, index) => {
                        return <div key={index} onClick={this.btnTapped}>{station}</div>
                    })
                }
            </div>
        )
    }
}

var cards = ["amazon", "aeo", "aerie", "barnes", "bloomingdales", "bbw", "bestbuy", "regal", "cvs", "ebay", "gyft", "itunes", "jcp", "panera", "staples", "walmart", "target", "sephora", "walgreens", "starbucks"];

    
ReactDOM.render(
    <Test stations={cards}/>, document.getElementById('test-div'));
<script src=""></script>
<script src=""></script>
<body>
  <div id="test-div"></div>
</body>

You should set a function to onClick attribute, not call it. Should be: onClick={this.btnTapped} instead of onClick={btnTapped()}.

Also, it is possible to do like this:

<div 
  onClick={function(e) {
    this.btnTapped(); //can pass arguments this.btnTapped(foo, bar);          
  }}
 >

It's usually used when you need to pass an argument to your function.

Also, to be able to get component's context from the external function, you should use bind(this) method. Like: onClick={btnTapped.bind(this)}

And since you are using a scope function for mapping array, new context is created inside of: this.props.stations.map(function(station, index){}. And this is overridden. Just use an arrow function instead:

var stationComponents = this.props.stations.map((station, index) => {

   return <div onClick={this.btnTapped}><img src="img/test.png" />{station}</div>;

});
3

Note: Not a reactjs Expert :)

I am exploring reactjs right now and as of version 16.3.1 the arrow function worked for me

<button
    onClick={() => { console.log("button clicked");}}>
    button  
</button>
0

This is somewhat a noob sugesstion but please check the spelling of your onClick() function, I had spelt it wrong like onclick() and It took me a good hour to find it out.

3

You missed this keyword before function. Also you must provide function but not calling it

<div onClick={this.btnTapped}>

UPDATE:

You missed that you are redefines this in map callback function.

Use arrow function

this.props.stations.map((station, index) => {
  return <div onClick={this.btnTapped}><img src="img/test.png" />{station}</div>;
});

or bind context to function

this.props.stations.map(function (station, index) {
  return <div onClick={this.btnTapped}><img src="img/test.png" />{station}</div>;
}.bind(this));
1

Whenever you want to use a function in the render method, first you need to bind those methods in the constructor. One more thing is when you don't want to pass any arguments to the methods that you need to call use this onClick = {this.btnTapped} instead of onClick = {this.btnTapped()}. Thank you.

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

export default class Test extends Component {
constructor (props) {
    super(props);
//set cards value in state then you don't need to use props...
    this.state = {
        cards: ["amazon", "aeo", "aerie", "barnes", "bloomingdales", 
        "bbw","bestbuy", "regal", "cvs", "ebay", "gyft", "itunes", 
        "jcp", "panera", "staples", "walmart", "target", "sephora", 
        "walgreens", "starbucks"]
    }
    this.btnTapped = this.btnTapped.bind(this);
    // bind all the methods which you're using the "this.state" inside it....
}

btnTapped (card) {
    console.log("Coming here:::" + card)
}

render() {
    var cards = this.state.cards
    return (
        <div>
            {/* if you don't want to pass an arguments use this... */}
            {
                cards.map((card, i) => 
                    <button key = {i} onClick = {this.btnTapped}>{card}</button>
                )
            }
            {/* if you want to pass arguments use this  */}
            {
                cards.map((card, i) =>
                    <button key = {i} onClick = {(e) => this.btnTapped(card)}>{card}</button>
                )
            }
        </div>
    );
}
}
ReactDOM.render(<Test />, document.getElementById('test-div'));

Just my 2 cents for someone whose issue is not resolved with this thread's answer. I face the similar issue and after debugging I found that my button had a 'z-index' of -9999 so it was behind a layer and hence the click was not reaching it. I changed the z-index to a positive value of 1 and the click got captured.

For those who are facing this issue, it may occur due to some CSS issue as well

For me, it worked by removing the CSS property named "pointer-events". In my CSS, it was set to none. i.e.

pointer-events: none;

I just removed it from my CSS and the click event starts to work in React!

This is an old post, still posting my answer as I faced same issue in 2021 and none of the answers above helped.

I added bundle.js in my index.html file. And html-webpack-plugin was also adding it for me. Loading bundle.js twice seemed to have caused the issue. It worked fine after removing that reference from index.html

0

If you are using webpack, make sure your output file which you configured in webpack.config.js (usually bundle.js) is not added in your index.html file.

This solved the problem for me.

In my case the div containing the button was wrapped by an outer div. Because of which the events were not getting triggered. I also had an input box alongside the button, Because of that outer div, I was also not able to click on the input box.

In order to understand what was causing the problem, I added a red border to the surrounding divs and then I came to know about the outer div which was wrapping my main div.

So my suggestion for such kind of problem would be to add a border to nearby elements like

border: '1px solid red'

And then try to figure out what is restricting the events.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

James H. Sterling

James H. Sterling

Environmental Science & Climate Journalist

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.

Share this article
Twitter Facebook Pinterest