14

I'm a beginner in React, and I'm a little confused about calling a function in React.

I saw the following ways and I don't know when to use each and which one.

  • handleAddTodo ={this.handleAddTodo}
  • handleAddTodo ={this.handleAddTodo()}
  • handleAddTodo ={handleAddTodo}
  • handleAddTodo ={this.handleAddTodo}
  • handleAddTodo ={handleAddTodo()}

Are these interchangeable? Could I do that to handle an event, the same way to call a function?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Anyname Donotcare
  • 11,113
  • 66
  • 219
  • 392
  • do you want to trigger an event from other component? – Abraham Gnanasingh Jul 14 '17 at 09:53
  • Are you sure you want to call a function not to pass it as a property of child component? – Yury Tarabanko Jul 14 '17 at 09:53
  • @YuryTarabanko : yeah i pass a function calling, this is a prop of a child, isn't passing a function implicitly considered as calling for it ? – Anyname Donotcare Jul 14 '17 at 09:58
  • 1
    @AnynameDonotcare "isn't passing a function implicitly considered as calling for it" no. You either pass a function (so that your child component could call it some time later aka "callback") or you call it and pass the result it returns. – Yury Tarabanko Jul 14 '17 at 10:00

6 Answers6

19

Are these interchangeable?

Short answer: No.


Let's take a look at the different snippets you've posted:


someFunction() vs someFunction

With the former syntax, you are actually invoking that function. The latter is just a reference to that function. So when do we use which?

  • You would use someFunction() when you want that function invoked and its result returned immediately. In React, this is typically seen when you split parts of your JSX code to a separate function; either for reasons of readability or reusability. For example:

    render() {
      myFunction() {
        return <p>Foo Bar</p>;
      }
      return (
        <div>
          {myFunction()}
        </div>
      );
    }
    

  • You would use someFunction when you want only to pass the reference to that function to something else. In React, this is usually an event handler that is passed down to another child-component via props so that that component can call the event handler when it needs to. For example:

    class myApp extends React.Component {
      doSomething() {
        console.log("button clicked!");
      }
      render() {
        return (
          <div>
            <Button someFunction={this.doSomething} />
          </div>
        );
      }
    }
    
    class Button extends React.Component {
      render() {
        return (
          <button onClick={this.props.someFunction}>Click me</button>
        );
      }
    }
    

someFunction() vs this.someFunction()

This has to do with the context of the function. Basically, "where is this function?". Is part of the current Component, then use this.someFunction(), is it part of the parent Component passed in as props, then use this.props.someFunction(). Is it a function inside the current method, then just use someFunction().

Obviously, there's a lot more to it than that, but it's the best basic summary I can give.

For a better understanding, have a read here. It is a great guide to how the this keyword works in Javascript and in React in particular.

Chris
  • 57,622
  • 19
  • 111
  • 137
4

If you want to call a function options 2 and with some assumptions 5 should work.

If you want to actually pass a function as a property to some child component so that it could call it later (say to notify your root element on some event) then option 1 (with prebind) and 3 (with defining a variable const {handleAddTodo} = this and prebind :) ) should work

// this works if handleAddTodo was prebinded or doesn't use this
handleAddTodo ={this.handleAddTodo} 

// this probably wont work unless handleAddTodo is higher order function that returns another function
handleAddTodo ={this.handleAddTodo()} 

// This wont work unless you have a var/let/const that is referencing a function
handleAddTodo ={handleAddTodo} 

// Same as 1
handleAddTodo ={this.handleAddTodo} 

// 3 and 2 combined
handleAddTodo ={handleAddTodo()} 
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
3

To call the function you have to add ()

{this.handleAddTodo()}   

About handling events - Handling#Events

Arrow Functions - Functions#ArrowFunctions

fauster01
  • 66
  • 3
2

In ES6 you can use normal function or Arrow Function:

Function1 (Normal Function)

functionA(){
   //Something here
}

Then should call this.functionA()

Function2 (ArrowFunction)

functionA = () => {
   //SomeThing Here
}

Then should call this.functionA

*Function3 (Eg: in a const of React) *

const A = (functionTest) =>{
  return (
     <div>{functionTest}</div>
    );
}

functionTest is mapStateToProps in React :)

I hope it is helpful for you :)

Voi Mập
  • 779
  • 3
  • 7
  • 22
2

this is correct -> handleAddTodo ={this.handleAddTodo} When function passing to child component you have to bind your function like this handleAddTodo ={this.handleAddTodo.bind(this)}. below code help out your doubt.

Simple Example

import React from 'react';

class App extends React.Component {

   constructor(props) {
      super(props);

      this.state = {
         data: 'Initial data...'
      }

      this.updateState = this.updateState.bind(this);

   };

   updateState() {
      this.setState({data: 'Data updated...'})
   }

   render() {
      return (
         <div>
            <button onClick = {this.updateState}>CLICK</button>
            <h4>{this.state.data}</h4>
         </div>
      );
   }
}

export default App;

Child Events

import React from 'react';

class App extends React.Component {

   constructor(props) {
      super(props);

      this.state = {
         data: 'Initial data...'
      }

      this.updateState = this.updateState.bind(this);
   };

   updateState() {
      this.setState({data: 'Data updated from the child component...'})
   }

   render() {
      return (
         <div>
            <Content myDataProp = {this.state.data} 
               updateStateProp = {this.updateState}></Content>
         </div>
      );
   }
}

class Content extends React.Component {

   render() {
      return (
         <div>
            <button onClick = {this.props.updateStateProp.bind(this)}>CLICK</button>
            <h3>{this.props.myDataProp}</h3>
         </div>
      );
   }
}

export default App;

Refer here

vnomvk
  • 113
  • 5
2

You can trigger events with this.props.someProps(). Check the following sample.

import React, { Component } from 'react';    

class AddToDo extends Component {
   render() {
      return (
         <button onClick={ev => this.props.handleAddToDo(ev, 'hello')}>
            {this.props.title}
         </button>
      )
   }
}

class Todos extends Component {
   handleAddToDo(ev, someVal) {
      // do something
   }

   render() {
      return (
         <AddToDo title="Add" handleAddToDo={(ev, someVal) => this.handleAddToDo(ev, someVal)} />
      )
   }
}

export default Todos;
Abraham Gnanasingh
  • 837
  • 2
  • 10
  • 31