1

I'm creating a table with Material UI inside a Webpack + ReactJS project

I want to add an 'icon menu' with one 'menu item' that would allow the user to delete the line and the linked datas. Here is the (revelant) code:

export default class GufreFile extends React.Component {
    render(){
        function alertTest() {
            console.log('hello there');
        }

        return (
            <TableRow>
                //...
                <TableRowColumn>
                    <IconMenu
                        iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
                        anchorOrigin={{horizontal: 'right', vertical: 'top'}}
                        targetOrigin={{horizontal: 'right', vertical: 'top'}}
                    >
                        <MenuItem primaryText="Delete" onTouchTap={ alertTest }/>

                    </IconMenu>

If I try with this code, everything works perfectly, I get 'hello there' if I click on my menu link.

However, if I do the following:

export default class GufreFile extends React.Component {
    render(){
        function alertTest(data) {
            console.log(data);
        }

        return (
            <TableRow>
                //...
                <TableRowColumn>
                    <IconMenu
                        iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
                        anchorOrigin={{horizontal: 'right', vertical: 'top'}}
                        targetOrigin={{horizontal: 'right', vertical: 'top'}}
                    >
                        <MenuItem primaryText="Delete" onTouchTap={ alertTest( this.props.data.id) }/>

it will make show my datas' id inside my console when I reload the page.

I don't know if this is a bug, or if I misunderstood anything.

Can someone help?

Thank you in advance

1 Answer 1

1

You should bind the handler in the constructor of the class as this will reference the element.
Also you should put the alertTest outside the render function.

export default class GufreFile extends React.Component {
    constructor(props){
        super(props);
        this.alertTest = this.alertTest.bind(this);
    }
    alertTest = (e) -> {
        console.log(e.target); // you can access the element values here
    }
    // render...
    <MenuItem primaryText="Delete" onTouchTap={alertTest}/>
    // rest of code

I've made a snippet as an example of how to get props and access the element via the event:

class App extends React.Component {
			constructor(props){
      	super(props);
        this.colorMe = this.colorMe.bind(this);
      }
      colorMe(e){     
        e.target.style.backgroundColor = '#abcdef';
        e.target.innerHTML = this.props.someProp;
      }

      render() {
        return (
          <div className="App">
            <div id="clickable" onClick={this.colorMe} />
          </div>
        );
      }
    }
    
    ReactDOM.render(<App someProp="this is some external prop!"/>, document.getElementById("root"));
#clickable{
  width: 150px;
  height: 150px;
  background-color: #ccc;
  text-align: center;
  padding: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you a lot, i now know why I had these issues earlier! However, my main problem isn't solved yet: if I use the following ` alertTest = (data) -> { console.log(data); // you can access the element values here }` with onTouchTap={ this.alerttest(this.props.data.id), I still get all my ids in my console log (I tested with onTouchTap and onClick)
you should not invoke the method inside the render only pass it as a ref onTouchTap={alertTest}
I guess it's more secure, but then again, is there a way to do so?
it's not a matter of security. it's performance issue. when you create a function like that you are not passing in a ref to a function but creating an instance of a function and this will create it on each render. really bad for performance. when you bind it in the constructor you only instantiating the function once. why would you want to pass a parameter to this function anyway?
Sorry for not answering earlier, and thank you again for your answers! As you saw in my original question I'm creating a table. However, I need to be able to delete a row, and the only way I know is to pass the id to the controller via an Ajax request. So I don't really know any other way to do so

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.