2

I am learning React and I came across event handlers. In React, it is recommended to bind the function to this, before using it as an event handler. However, I did not bind it and I am still getting the desired output. Below is my code:

import React, { Component } from 'react';

class Experiment extends Component {
    constructor(props){
        super(props);

    }

    clickEvent(e){
            e.preventDefault();
            document.getElementById('change').innerHTML="This text changed";
        }

    render(){
        return(
            <div>
                <p id='change'>This paragraph will change</p>
                <button onClick={this.clickEvent}>Press me</button>
            </div>
            );
    }
}

export default Experiment;

As you can see, I haven't bound clickEvent() to this, yet the onClick event works without a hitch. Why is that? I assumed that I would have gotten an undefined error or something else

3 Answers 3

5

The reason this works is because you aren't referring to anything using 'this' within your clickEvent function. Within javascript, the 'this' variable within a function refers to the object that the function was called from.

To prove this, try accessing this.props or this.state, they will return undefined because you are missing your .bind(this)

.bind() will return a new function, that will stick with a given 'this' context, no matter where it is called from.

const myObj = {
    name: 'John',
    testFunction: function() {
        console.log(this.name);
    }
};

const testFunction = myObj.testFunction;

myObj.testFunction(); // John
testFunction(); // undefined


const testFunctionBound = testFunction.bind(myObj);
testFunctionBound(); // John
Sign up to request clarification or add additional context in comments.

1 Comment

I love it @Jye. Nice one.
1

As a theoretical sidenote to Jye Lewis answer above, and clarifications on the subject.

There are 3 regular ways of binding context to functions in react:

  1. Bind (usually in constructor)
  2. Class field/property with arrow
  3. Arrow in render

example code:

class ThisDemo extends Component {
  constructor(props) {
    super(props); 

    // 1. In constructor 
    this.onClick = this.onClick.bind(this);
  }

  // 2. Class field/property with arrow
  onClick = () => {  
  }

  render() {
    // 3. Arrow in render
    return (
      <button type="button" onClick={event => console.log(event)}>
        Pretty Button
      </button>
    ); 
  }
}
export default ThisDemo; 

Ups and downs

  1. Bind (usually in constructor)
    • ups: On same protetype no matter how big N is.
    • downs: Polluting the constructor
  2. Class field/property with arrow
    • ups: Very convenient , nice syntax. For N components create N different functions.
    • downs: In some cases, loss of performance. (N high)
  3. Arrow in render
    • ups: Can catch events in a simple way, good for performing logic without passing down props for callback parameters.
    • downs: You are passing a new inline arrow function with every render. Always a new reference, which could cause re-rendering.

Wisdoms

You should only bind with.bind() or arrow function if you're going to pass the function around.

Class field/property with arrow is convenient but could be inefficient if many This.Demo components

Be pragmatic until you can't be. The performance issues are almost never a problem, and they might change how it works in the future.

Reference

  1. This article helped me alot in understanding the different methods.
  2. Also this one.

Comments

1

You can use arrow functions instead of creating constructor and calling both super and

bind methods.

An arrow function does not have its own this, but it has the this value of the enclosing execution context. Arrow Functions lexically bind their context so this actually refers to the originating context. That’s called Lexical Scoping if you’re into naming things. Basically, it saves us from doing .bind(this) in our code. Note that this is an experimental feature in JS, which means it’s not yet accepted into ECMAScript standard

So, instead of doing this way:

//with binding in a constructor and calling super method
class Experiment extends Component {
  constructor(props) {
    super(props); 

    // 1. In constructor 
    this.onClick = this.onClick.bind(this);
  }
...
}

You can do it in a cleaner way like below:

  //with arrow 
  handleOnClick = product => {  
     ...
  }

And in your render method you do something like:

class Experiment extends Component {
  render() {
    return (
        <button onClick={ () => this.handleOnClick(product) } >
            Add new product
        </button>
    );
  }
}

Read more about arrow functions in this article:

Comments

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.