Dan Zuzevich
Dan Zuzevich

Reputation: 3831

React/Redux Wrong This Context

Okay, so this is pretty embarassing since I am pretty experienced with React, but I am having trouble wrapping my head around why this.props is not recognized in my handlePress component method.

I am unsure as to why I am able to access this.props inside of the following methods:

But when I attempt to call this.props inside of handlePress React says it is undefined. In the code below, you can see that I attach an onPress handler to the Button, which calls handlePress. The handlePress method is called correctly, but the app crashed when I try to access props inside of it.

This does not work unless I do, this.handlePress = this.handlePress.bind(this) inside of the constructor. I am confused as to why I can access the correct this context inside of the other methods when I do not bind them in the constructor.

Any help?

class LoginForm extends Component {
  constructor(props) {
    super(props)
  }

  renderButton() {
    if(this.props.loading) {
      return <Spinner size="large" />
    }

    return (
      <Button onPress={this.handlePress}>
        Login
      </Button>
    )
  }

  renderError() {
    if(this.props.error) {
      return (
        <View style={{ backgroundColor: 'white', }}>
          <Text style={{ color: 'red', alignSelf: 'center' }}> 
            { this.props.error } 
          </Text>
        </View>
      )
    }
  }

  handlePress() {
    const { email, password } = this.props
    this.props.loginUser({ email, password })
  }

  render() {
    const { email, updateInputField, password } = this.props

    return (
      <View>
        <Card>

          {/*
            E-Mail
          */}
          <CardSection>
            <Input
              value={email}
              onChangeText={value => updateInputField('email', value)}
              label="Email"
              autoCorrect={false}
              placeholder="[email protected]"
            />
          </CardSection>

          {/*
            Password
          */}
          <CardSection>
            <Input
              value={password}
              onChangeText={value => updateInputField('password', value)}
              label="Password"
              autoCorrect={false}
              secureTextEntry
            />
          </CardSection>

          { this.renderError() }

          <CardSection>
            { this.renderButton() }
          </CardSection>

        </Card>
      </View>
    )
  }
}

const mapStateToProps = ({ auth }) => {
  const { email, password, loading, error } = auth
  return { email, password, loading, error }
}

export default connect(
  mapStateToProps,
  {
    updateInputField,
    loginUser
  }
  )(LoginForm)

Upvotes: 1

Views: 54

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281854

When you write:

<Button onPress={this.handlePress}>
    Login
</Button>

You are not invoking the handlePress function within the context of the current component, instead you are assigning a reference of it to the onPress prop being passed on to the Button.

Now when the button triggers the handlePress method, is when it gets the context. It won't refer to the context you want it to run in, unless you bind the handlePress method in constructor or use arrow function like

<Button onPress={(e) => this.handlePress(e)}>
    Login
</Button>

or

handlePress = (e) => {} 

Upvotes: 3

Related Questions