Reputation: 891
I have this simple code in a react component:
render(){
return(
<List>
<MenuItem onClick={this.onItemClick} key={1}>Menu item 1</MenuItem>
<MenuItem onClick={this.onItemClick} key={2}>Menu item 2</MenuItem>
<MenuItem onClick={this.onItemClick} key={3}>Menu item 3</MenuItem>
</List>
)
}
onItemClick = (event) => {
console.log(event, event.target, event.target.key); //???
}
When I click on a list item, I want to retrieve its reference to assign the selected
property of that item.
The event.target
gives a <li>
object instead of a <MenuItem>
object, so event.target.key
returns undefined
The material-ui docs don't give any explanation on how to handle events unfortunately.
What am I doing wrong?
Upvotes: 3
Views: 3082
Reputation: 4387
event.target
gives a li
element because the browser works with the DOM, not the virtual structure that React keeps in memory.
There is no MenuItem
element on the rendered page. Instead, there's the elements that are rendered by MenuItem
s.
Click events come from actual DOM elements like div, input, li. Why not from MenuItem? Because there's no <MenuItem>
on the page. When you click on the elements, you click on <li>
s, not <MenuItem>
s.
What you want to do is achievable by setting an "imaginary" click handler on the virtual <MenuItem>
:
<VirtualElement onClick={virtualClickHandler} />
Then, when rendering the real DOM element <li>
, the VirtualElement will set on it a real click handler:
class VirtualElement {
realClickHandler (e) { // Let's assume you've bound this in the constructor
// do stuff with "e" and "this.props"
}
render () {
return <li onClick={realClickHandler} />
}
}
Now, realClickHandler
's scope contains this
and e
. This means, it can read both the state & (virtual) props of the VirtualElements and the event object.
The final part - the only thing left is the virtualClickHandler
. Where does it reside? In this.props
. Because when earlier you said <VirtualElement onClick={virtualClickHandler} />
, this onClick handler gets written on the props
object of the VirtualElement.
What you want to do is call the virtualClickHandler from the realClickHandler, which sees both the event and the this object:
realClickHandler (e) {
// Here you can tell the virtualClickHandler whatever it needs to know:
this.props.onClick({
event: e,
key: this.props.key
});
}
Upvotes: 1
Reputation: 281606
In order to get the clicked Item, you can either use arrow function or bind in render which isn't the most correct approach
<MenuItem onClick={() => this.onItemClick(1)} key={1}>Menu item 1</MenuItem>
or write a wrapper around MenuItemClick like
class ExtendedMenuItem extends React.Component {
onClick=() => {
this.props.onClick(this.props.id);
}
render(){
const {id, children, ...others} = this.props;
return <MenuItem onClick={this.onClick} key={id} {...others}>children</MenuItem>
}
}
and then use it like
<ExtendedMenuItem onClick={this.onItemClick} id={1}>Menu item 1</ExtendedMenuItem >
Upvotes: 2
Reputation: 1416
you can do something like that :
render(){
return(
<List>
<MenuItem onClick={this.onItemClick(1)} key={1}>Menu item 1</MenuItem>
<MenuItem onClick={this.onItemClick(2)} key={2}>Menu item 2</MenuItem>
<MenuItem onClick={this.onItemClick(3)} key={3}>Menu item 3</MenuItem>
</List>
)
}
onItemClick = itemId=>(event) => {
console.log(itemId,event, event.target, event.target.key); //???
}
Upvotes: 0