menu

Questions & Answers

React onclick listener doesn't work as expected

Simple thing, I'm supposed to make a counter app that increments/decrcements/resets a counter if I click on the corresponding button (up/down/reset).

I'm new to React but know some js.

I get this as error message

Warning: Expected `onClick` listener to be a function, instead got a value of `string` type.
    in button (created by App)
    in div (created by App)
    in div (created by App)
    in App
<script type=text/babel>
    class App extends React.Component {

        constructor(props) {
            super(props)
            this.state = {count: 0} // init count
        }
        
        render() {
            return <div className="counter">
                <div className="title">Counter</div>
                <div className="number">{this.state.count}</div>
                <div className="buttons">
                    <button onClick='incrementCounter()'>Up</button>
                    <button onClick='decrementCounter()'>Down</button>
                    <button onClick='resetCounter()'>Reset</button>
                </div>
            </div>
        }

        // why does this not work?
        incrementCounter(){
            this.setState( state => ({ count: this.state.count + 1 }) )
        }

        decrementCounter(){
            this.setState( state => ({ count: this.state.count - 1 }) )
        }

        resetCounter(){
            this.setState( state => ({ count: 0 }) )
        }
    }
    
    ReactDOM.render(<App/>, document.getElementById("root"))
</script>

What am I doing wrong?

Comments:
2023-01-20 23:25:03
onClick='incrementCounter()' needs to be onClick={this.incrementCounter}, and similar for the other onClick's
2023-01-20 23:25:03
(you almost certainly need to bind it in the constructor as well, since you're using class components. Actually that whole page starts with a perfect explanation of exactly what's wrong with your code - the part about binding is a bit further down.)
Answers(1) :

In JSX, you want to surround Javascript code with curly braces and for attributes, you omit the quotes to use curly brances.

Each onClick attribute should be surrounded by braces instead of quotes:

<button onClick={incrementCounter}>Up</button>
Comments:
2023-01-20 23:25:03
while what you say in the text of your answer is true, your code sample is completely wrong because you're calling incrementCounter in render. You're also overlooking that the OP's component is a class component.
2023-01-20 23:25:03
Yes, you're correct and the edit was made for calling the function instead of having the event reference it. The binding is unrelated to the error posted but OP should be aware of it as this will not reference the correct object.
2023-01-20 23:25:03
thanks for fixing that but this still won't work as this is a class component so there is no incrementCounter in scope