3

I've heard that passing an arrow function as a prop is not ideal because it creates a new function every time which will lead to performance issues. However, I'm not entirely sure how to completely move away from them, as can be seen by the example below:

class Home extends Component {

    onCardPress = (message) =>{
        alert(message)
    }

    render(){
        return(
            <View>
                <Card 
                    onCardPress={this.onCardPress}
                    message="Hello world!"
                />
            </View>
        )
    }
}

class Card extends Component {
    render(){
        const { onCardPress , message } = this.props;
        return(
            <TouchableOpacity
                activeOpacity={0.8}
                onPress={()=>{onCardPress(message)}}
            />
        )
    }
}

I have tried changing onPress in Card to be onPress={onCardPress(message)}, but I know this doesn't work because I am invoking the function rather than passing a function object to the onPress of TouchableOpacity. What is the 'proper' way or best practice to remove the arrow function in TouchableOpacity while still being able to pass the message parameter from the parent component Home?

Luke Tan
  • 2,048
  • 2
  • 13
  • 21

5 Answers5

0

If you want to avoid arrow function, you have to use bind(). Arrow functions will automatically bind "this".

  class Home extends Component {

      constructor(props) {
       super(props);
       this.onCardPress = this.onCardPress.bind(this);
      }

      onCardPress (message) {
        alert(message)
      }

      render(){
        return(
            <View>
                <Card 
                    onCardPress={this.onCardPress}
                    message="Hello world!"
                />
            </View>
        )
      }
  }



class Card extends Component {
    render(){
        const { onCardPress , message } = this.props;
        return(
            <TouchableOpacity
                activeOpacity={0.8}
                onPress={onCardPress(message)}
            />
        )
     }
 }
Harikrishnan
  • 9,688
  • 11
  • 84
  • 127
0

You could do:

class Card extends Component {
    pressHandler = () => this.props.onCardPress(this.props.message);

    render() {
        return (
            <TouchableOpacity
                activeOpacity={0.8}
                onPress={this.pressHandler.bind(this)}
            />
        );
    } }
Gabor Szekely
  • 1,108
  • 5
  • 14
  • Just wondering, is this functionally the same as the arrow function version i.e. performance wise its the same? Or does this avoid the performance issues of using arrow functions? – Luke Tan Feb 20 '19 at 05:00
  • There is a small benefit in that you are not creating a new function every time the event handler is triggered, however this is pretty negligible overall. – Gabor Szekely Feb 21 '19 at 00:00
0

As I understand it, the issue lies with calling bind inside of render, or returning the handler from yet another lambda, as this will create a new function each time. The conventional way to get around this problem is to bind your handler functions elsewhere -- like in the constructor. In your case, that could look like this:

constructor(props) {
    ....
    this.onCardPress = this.onCardPress.bind(this);
}

...

<Card 
   onCardPress={this.onCardPress}
   message="Hello world!"
/>
Kai
  • 2,529
  • 1
  • 15
  • 24
0

Given you alternative option as arrow function already answered in above post.

class Card extends Component {
   onClick = () => {
      const { onCardPress, message } = this.props;
      onCardPress(message);
    }
    render(){
        const { onCardPress , message } = this.props;
        return(
            <TouchableOpacity
                activeOpacity={0.8}
                onPress={this.onClick}
            />
        )
    }
}
QuokMoon
  • 4,387
  • 4
  • 26
  • 50
0

You don't need to pass the message prop because you can access it anywhere in the component. Just supply a function in the onPress prop. And in that function, just access the message prop of the component.

class Home extends Component {
  onCardPress = (message) => {
    alert(message)
  }
  render() {
    return (
      <View>
        <Card
          onCardPress={this.onCardPress}
          message="Hello world!"
        />
      </View>
    )
  }
}

class Card extends Component {
  onClick = () => {
    const { message, onCardPress } = this.props;
    onCardPress(message);
  };
  render() {
    return (
      <TouchableOpacity
        activeOpacity={0.8}
        onPress={this.onClick}
      />
    )
  }
}
Ken Labso
  • 885
  • 9
  • 13