-1

I'm trying to navigate inside the function _login rather than inline. In the function this.props.navigation is undefined. What's wrong there?

import React from 'react';
import { StyleSheet, Form, View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
import { Button, FormValidationMessage, FormLabel, FormInput } from 'react-native-elements';
import { AgendaScreen } from './AgendaScreen';

class HomeScreen extends React.Component {

  static navigationOptions = {
    title: 'Please sign in',
  };

  render() {
    return (
      <View style={styles.container}>
        <FormLabel>Username</FormLabel>
        <FormInput onChangeText={this.inputChanged} />
        <FormValidationMessage>{'This field is required'}</FormValidationMessage>
        <FormLabel>Password</FormLabel>
        <FormInput secureTextEntry={true} onChangeText={this.inputChanged} />
        <FormValidationMessage>{'This field is required'}</FormValidationMessage>
        <Button raised onPress={this._login} title="Sign in" />
      </View>
    );
  }

  inputChanged() {
    console.log('adfasdf');
  }

  _login() {
    this.props.navigation.navigate('Agenda');
    console.log('Logging in');
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  }
});

export default StackNavigator({
  Home: HomeScreen,
  Agenda: AgendaScreen
});
Asken
  • 7,679
  • 10
  • 45
  • 77
  • Possible duplicate of [Unable to access React instance (this) inside event handler](https://stackoverflow.com/questions/29577977/unable-to-access-react-instance-this-inside-event-handler) – Andrew Li May 04 '18 at 13:58

3 Answers3

1

You need to bind _login method to your class:

<Button raised onPress={this._login.bind(this)} title="Sign in" />

Or declare _login method as arrow function:

 _login = () => {
    this.props.navigation.navigate('Agenda');
    console.log('Logging in');
  }
Artem Mirchenko
  • 2,140
  • 1
  • 9
  • 21
  • Ah, super! I get the good old `bind` but I need to read up on the meaning of arrow functions in react. – Asken May 04 '18 at 13:54
  • 1
    Arrow functions haven't own context, so you don’t need to change context of this in callbacks and create wrappers. – Artem Mirchenko May 04 '18 at 13:59
1

When passing _login down to your Button component you lose the value of this.

The solution would be to bind this to _login, for example, inside the constructor:

this._login = this._login.bind(this);

Or you can use Arrow functions :

<Button raised onPress={() => { this._login() }} title="Sign in" />
Hamza El Aoutar
  • 5,292
  • 2
  • 17
  • 23
0

First, you are trying to use this inside a function that will be called by another component/function (Button).

That Button doesn't know this because it's not in the same context.

You need to bind the method to the current object.

To do this, I recommend to bind it in the constructor.

class HomeScreen extends React.Component {
    constructor(props, context) {
        super(props, context);
        this._login = this._login.bind(this);
    }

    render() {
        return (
            <View style={styles.container}>
                {/* MORE CODE */}
                <Button raised onPress={this._login} title="Sign in" />
            </View>
        );
    }

    // * MORE CODE *
}

Secondly, this should be done in the constructor instead of inline.

If it's done inline, then a NEW function is assigned to onPress and react will re-render that part without needing to.

The same happens with inline arrow functions.

EDIT

This second part only applies when:

  1. Using PureComponent
  2. Using shouldComponentUpdate to match the props

However, inline you are creating a different function each time react renders the component. Still bad practice.

EDIT 2 (ES6)

To prevent using a constructor you could use arrow functions but in a different way. Like this.

class MyComponent extends React.PureComponent {
  doWork = () => {
    // doing some work here.
  }

  render() {
    return <Text onPress={this.doWork}>Do Some Work</Text>
  }

}

This way you are creating the function only once per lifetime.

Leandro Soares
  • 2,902
  • 2
  • 27
  • 39