user3761761 user3761761 - 1 month ago 13
React JSX Question

Material UI List onClick fires click event on nested list

I have a material ui list in my one of the component. When I click any item of this list, I go to another listView. I am using router to go to another listView. And using onClick method. Whenever I click any list item of first list I print "firstList clicked". and whenever I click any item if second list, it print "secondList clicked".

Here is my Problem:
When I click the ListItem of first list, the console.log("secondList clicked") also gets printed with "firstList Clicked" automatically. I have four list items in second list, so my console print output looks like this

firstList Clicked
secondList Clicked
secondList Clicked
secondList Clicked
secondList Clicked

Why is this happening?

Here is my code.

SecondList code

class TagListItemDetails extends Component {
handleClick() {
console.log("secondList clicked")
}

handleButtonClick() {
browserHistory.push("TagList")
}

render() {

return (
<MuiThemeProvider>
<div>
<List id="parent-list-tags">
<ListItem primaryText="Kitchen" onTouchTap={this.handleClick()}/>
<ListItem primaryText="Beach" onClick={this.handleClick()}/>
<ListItem primaryText="Marriage" onClick={this.handleClick()}/>
<ListItem primaryText="Garden" onClick={this.handleClick()}/>
</List>
<div className="backButton">
<RaisedButton backgroundColor="#293C8E" label="Back" onClick={this.handleButtonClick} labelColor="white">

</RaisedButton>
</div>
</div>
</MuiThemeProvider>

);
}
}

const mapStateToProps =(state) =>{
return {
tags: state.tagReducer
};
};

function matchDispatchToProps(dispatch){
return bindActionCreators({tagSelected: tagSelected}, dispatch);
}

export default connect(mapStateToProps, matchDispatchToProps)(TagListItemDetails);


firstList

export default class TagList extends Component {


handleClicked() {
console.log("firstList Clicked")
browserHistory.push("TagListItemDetails")
}

render() {

return (
<div>
<List id="parent-list-tags" >
<ListItem primaryText="Scene" onClick={this.handleClicked} />
<Divider/>
<ListItem primaryText="Actors" onClick={this.handleClicked} />
<Divider/>
<ListItem primaryText="Emotions" onClick={this.handleClicked} />
<Divider/>
<ListItem primaryText="Actions" onClick={this.handleClicked}/>
<Divider/>
<ListItem primaryText="Objects" onClick={this.handleClicked}/>
<Divider/>
<ListItem primaryText="Compliance" onClick={this.handleClicked} />
</List>
<AddButton />
</div>

)
}
};

Answer

The problem is that in the SecondList, you are invoking the handleClick method as soon as the component is loaded. Try removing the parentheses () from the onClick handler. So instead of

<ListItem primaryText="Beach" onClick={this.handleClick()}/>

you can use:

<ListItem primaryText="Beach" onClick={this.handleClick}/>
------------------------------------------------------^^ No parentheses here

If you want to pass an argument to a click handler passed as a prop you can use the following:

onClick={() => this.props.itemSelected(2)}

// or

onClick={this.props.itemSelected.bind(this, 2)}

Here is a demo: http://codepen.io/PiotrBerebecki/pen/YGRQrG