85

I am having trouble with react-native onPress Feature. The onPress should only work when it is actually been triggered by a touch event (i suppose) , that is when i press the button on the screen. But it seems the onPress gets triggered itself when the render function is called. When i try to press manually, it doesn't work.

  import React, { Component } from 'react';
  import { PropTypes, Text, View ,Alert } from 'react-native';
  import { Button } from 'react-native-material-design';

export default class Home extends Component {
  
  render() {
    return (
          <View style={{flex:1}}>
            <Button value="Contacts" raised={true} onPress={this.handleRoute('x')} />
            <Button value="Contacts" raised={true} onPress={this.handleRoute('y')} />
            <Button value="Contacts" raised={true} onPress={this.handleRoute('z')} />
          </View>
          );
}
handleRoute(route){
  alert(route) // >> x , y, z 
    }
}

  module.exports = Home;

What am i missing ? Is there something wrong with the way i have assigned or this is some bug ? Any suggestion is highly appreciated.

Video

Community
  • 1
  • 1
Sijan Shrestha
  • 2,136
  • 7
  • 26
  • 52
  • I've only touched reactjs once, but I think you are calling the function instead of assigning it. – cipher Feb 19 '17 at 16:14

5 Answers5

222

try to change

onPress={this.handleRoute('x')} // in this case handleRoute function is called as soon as render happen

to

onPress={() => this.handleRoute.bind('x')} //in this case handleRoute doesn't called as soon as render happen

Manjeet Singh
  • 4,382
  • 4
  • 26
  • 39
  • 7
    Any idea on why there is this behavior? – Sijan Shrestha Feb 20 '17 at 04:05
  • 2
    not clearly(I don't want to provide false info), will let you know soon – Manjeet Singh Feb 20 '17 at 10:25
  • 6
    I understood it after a lot of time spend in it. It's very confuse, but when you set this: onPress={this.click(args)} it's mean you're calling a function and this function was called when render() is called or when the button/touchable is created. So, you need to use onPress={() => this.function(args)}. Is it clear? – Marcus Feb 12 '19 at 00:11
  • 1
    But in my case there is function component behaviour so this or bind both is not working. Please assist me – cakePHP Jun 06 '20 at 14:08
105

You can change to this:

onPress={this.handleRoute.bind(this, 'x')}

or this:

onPress={() => this.handleRoute('x')}

The reason is that onPress takes a function as an argument. In your code, you are calling the function and returning the result immediately (when render is called) rather than referencing the function for React to call later on the press event.

The reason you need the bind(this) is because the function loses it's bound instance when you just do (this.handleRoute) and you have to tell it which this to use. The bind function takes the other arguments to call on the function later. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind for more descriptive info on bind.

There is another way in which you can bind in the constructor. You can read about ways to handle this in React here: https://facebook.github.io/react/docs/handling-events.html

bhelx
  • 1,107
  • 1
  • 6
  • 6
  • 1
    I was stuck on this for 2 hours as I m new in React Native ... but your answer solved it in a min. Thanks alot – Vaibhav Jun 20 '19 at 21:58
  • 1
    Thanks a lot for the precise answer and explanation for a React Native newbie! – Quintin Aug 19 '19 at 17:03
5
onPress={this.handleevent.bind(this, 'A')}

or use this:

onPress={() => this.handleevent('B')}
Faizan Amin
  • 398
  • 5
  • 16
Shivo'ham 0
  • 1,333
  • 11
  • 19
4

Change

onPress={this.handleRoute('x')}

to

onPress={()=>this.handleRoute('x')}

Otherwise, the function gets invoked as soon as the render method gets called.

Pumuckelo
  • 323
  • 1
  • 9
0

The reason for such behaviour is on every render, reference to the function is created.

So, to avoid that, use bind function OR arrow function to call on onPress

Kushal Desai
  • 119
  • 2
  • 11