Christian LSANGOLA
Christian LSANGOLA

Reputation: 3317

Pros and Cons of React/ JSX method definitions

I would like to understand the real difference between:

<MyComponent myProp = { ()=> this.myMethod } 
// and
<MyComponent myProp = { this.myMethod }

Is it appropriate to use:

<MyComponent myProp = { () => this.myMethod() } 
// or 
<MyComponent myProp = { this.myMethod() }

Why is the bind() function sometimes called without the this parameter like the following examples:

<MyComponent myProp = { () => this.myMethod.bind () }  
// and 
<MyComponent myProp = { this.myMethod.bind(this) }

What are the advantages of the following two ways of defining a method:

myMethod = (event) => {}
// and  
myMethod(event){}

Upvotes: 0

Views: 232

Answers (3)

Adam Johnston
Adam Johnston

Reputation: 1411

First of all, the difference between an arrow function () => { stuff } and a regular function declaration function() { stuff } is that an arrow function automatically binds itself to whatever declared it. This is very useful in JSX. Let's say for example you have a form that holds its own state and then you have a separate input component that needs to change that state. If you created an onChange method like this handleChange(e) { change this.state } and then passed it to the input, the input would then change its own state because it is now the owner of the method. So this is why you need to then declare this.handleChange.bind(this) (usually in the constructor). However, if you declared your method like this handleChange = e => { change this.state } then it is already binded to the creator (the form in this case) and you don't need to manually bind it.

As far as the difference between myProp = { this.myMethod } and myProp = { () => this.myMethod() }, I'm not entirely sure. When I declare a prop as an arrow function, I'm usually trying to pass an extra argument. This is because you couldn't do this myProp = { this.myMethod(extraValue) } because javascript then thinks you're trying to call the method immediately. So in this case I would set the prop like this myProp = { e => this.myMethod(e, extraValue) } so that the method will not be called until it's triggered. But in a case when you are not trying to pass extra arguments, I don't know why you would declare it like this.

As far as calling the bind method with no argument, I have never seen this, nor do I understand what it would do. Maybe it defaults to this, but that would not be good practice because you would want to be explicit about what you are trying to bind to the method/function. As far as I understand, the bind method needs at least one argument.

Hope this helps. I know it's not a great answer, but I hope it gives you some insight as to what's going on.

Upvotes: 0

Tyler
Tyler

Reputation: 1891

I would like to understand the real difference between:

<MyComponent myProp = { () => this.myMethod } 
// and
<MyComponent myProp = { this.myMethod }

A: The first function declaration binds the method to the scope (this) of the component it is within. The second declaration doesn't necessarily, and instead relies on you to do that where the method is defined (see more in the defining a method question below).

Q: Is it appropriate to use:

<MyComponent myProp = { () => this.myMethod() } 
// or 
<MyComponent myProp = { this.myMethod() }

A: I can't think of a time when it is appropriate to use either of these two syntaxes. This format will cause the method to be run every time the jsx is rendered (a lot)!

Q: Why is the bind() function sometimes called without the this parameter like the following examples:

<MyComponent myProp = { () => this.myMethod.bind() }  
// and 
<MyComponent myProp = { this.myMethod.bind(this) }

A: I don't think the top syntax is valid. The bottom syntax is equivalent to using a lambda <MyComponent myProp = () => {}, as they both bind the function's scope to that of the component that contains this jsx.

Q: What are the advantages of the following two ways of defining a method:

myMethod = (event) => {}
// and  
myMethod(event){}

A: The first method declaration binds the method to the scope of the component it is a part of. The second method does not, so if you pass it to a child component, it will adopt the child component's scope (this).

Highly Opinionated: My preferences are shown in this sample:

class MyComponent extends React.Component<> {
  // Here we define the method and bind it to this component's scope
  myMethod = () => {}

  render() {
    return (
      // Now add the method as a prop
      <MyComponent myProp = {this.myMethod}>
    );
  }
}

Upvotes: 1

Chaim Friedman
Chaim Friedman

Reputation: 6263

I will attempt to go thru each of your points of confusion and attempt to clarify.

<MyComponent myProp={() => this.myMethod} />

In this case, you are passing an anonymous arrow function to your component, and when this arrow function gets called it will attempt to call your method. I say attempt because you are not actually invoking this.myMethod which you can see by the missing parens. This is the same as the following code.

function somOtherFunc() {
  console.log("I will not run");
}

function myFunction() {
  somOtherFunc;
}

myFunction();

In this case however <MyComponent myProp = { this.myMethod }, this.myMethod will actually get called since the function that is getting passed as a prop is the actual function.

<MyComponent myProp = { ()=> this.myMethod() } This case is similar to your first case, except this one will actually work since there are parens therefor there is an invocation. This is the same as the following code.

function somOtherFunc() {
  console.log("Now I will run");
}

function myFunction() {
  somOtherFunc();
}

myFunction();

As for using bind, this really comes down to whether or not there will be a need to bind the context of this in the method that is getting called. I would recommend reading thru this for that to make more sense to you. Truth be told, if you have no need to bind your this keyword, you really don't need to use the bind method at all, unless if you wanna pass arguments to your method, but this too can be achieved without using bind. Consider the following code as an example of what I mean.

clickhandler = (number) {
  console.log(number); //10
}

render() {
  return (
    <button onClick={() => this.clickhandler(10)}>Click me</button>
  );
}

Finally, for your last point, you can declare a function in JS using the arrow syntax such as this myMethod =(event)=>{} or you can use the function keyword such as this myMethod(event){}. The difference between the 2 comes back to understanding how this works in JS, and for that I would strongly urge you to read the article I linked above.

Upvotes: 1

Related Questions