Reactjs expected onclick listener to be a function instead got type Object

Seems quite common to find people on StackOverflow post about the “expected onclick listener to be X”. Let’s look at what the user posted :

class CharacterList extends Component{

    render(){
        return(
            <div>
            <h3>Characters</h3>
        <ul>
        {this.props.characters.map((character)=>{
            return(<li key={character.id}>{character.name}
                <div
                onClick={this.props.addCharacterById(character.id)}
                >+</div>
                </li>);
        })}
        </ul>
            </div>

            )
    }
}

The problem here is that he’s invoking the function immediately and then what’s left is the return value, which might not be a function!

What he can do instead is wrap that function call inside an arrow function to solve your problem.

It’ll call the inner function once you onClick:

import React,{Component} from 'react';
import {connect} from 'react-redux';
import {addCharacterById} from '../actions';
import {bindActionCreators} from 'redux';


class CharacterList extends Component{

    render(){
        return(
            <div>
            <h3>Characters</h3>
        <ul>
        {this.props.characters.map((character)=>{
            return(<li key={character.id}>{character.name}
                <div
                onClick={() => this.props.addCharacterById(character.id)}
                >+</div>
                </li>);
        })}
        </ul>
            </div>

            )
    }
}

function mapStateToProps(state){
    return {
        characters:state
    }
}




export default connect(mapStateToProps,{addCharacterById})(CharacterList);

There’s diferent ways of doing this, you could for example bind the parameter to the function, like:

{this.props.characters.map((character)=>{
    return(<li key={character.id}>{character.name}
        <div
        onClick={this.props.addCharacterById.bind(null, character.id)}
        >+</div>
        </li>);
})}

Just shared as an example, so that the user understands what’s going on and why the first approach is more readable. You may want to look into why .bind in render is a bad practice by reading the article never bend in render

Obs: Above I’ve put an example that used inline functions to expose the most basic solution and would advise that it’s important for the reader to read about the topic regarding inline functions performance here

comments powered by Disqus