0

I very need your help. I am trying to make a JSON object users in my state properties to check how my authentification works. But when I tried to get access I had received the error "Cannot read property 'state' of undefied" and error arrow pointed on this part of code const { users, textInputEmail, textInputPassword } = this.state. Also, when I tried to check users it also showed 'undefined'. What have I done wrong?

import React, { Component } from 'react'
import { View, TextInput } from 'react-native'
import { MyButton, ErrorMessage } from '../uikit'
import { FormStyle, InputStyle } from '../constants/styles'
import { SIGN_IN, SUCCESS } from '../routes'

export class LogIn extends Component {

    state = {
        users: {
            user: [
                {
                    name: 'john1303@ukr.net',
                    password: '12345678'
                },

                {
                    name: 'steve13@gmail.com',
                    password: '87654321'
                }

            ],
        },
        textInputEmail: '',
        textInputPassword: ''
    }

    isUser() {
        console.log(users)
        const { users, textInputEmail, textInputPassword } = this.state
        let currentUser, password;

        currentUser = users.map((user) => user.name == textInputEmail ? user : 'unknown')

        if (currentUser == 'unknown')
            return alert('Incorrect user or password!')
        else {
            if (currentUser.password == textInputPassword)
                this.props.navigation.navigate(SUCCESS)
        }
    }

    render() {
        const { mainContainer, buttons } = FormStyle
        const { container, text } = InputStyle

        return (
            <View>
                <View style={mainContainer}>
                    <View style={container}>
                        <TextInput
                            style={text}
                            placeholder={'Email/Login'}
                            onChangeText={(value) => this.setState({ textInputEmail: value })}
                        >
                        </TextInput>
                        <ErrorMessage errorText={'Incorrect email'} />
                    </View>

                    <View style={container}>
                        <TextInput
                            style={text}
                            placeholder={'Password'}
                            secureTextEntry={true}
                            onChangeText={(value) => this.setState({ textInputPassword: value })}
                        >
                        </TextInput>
                        <ErrorMessage errorText={'Incorrect password'} />
                    </View>

                    <View style={buttons}>
                        <MyButton
                            name={'Log in'.toUpperCase()}
                            onPress={this.isUser} />
                        <MyButton
                            name={'Sign in'.toUpperCase()}
                            onPress={() => this.props.navigation.navigate(SIGN_IN)} />
                    </View>
                </View>
            </View>
        )
    }
}

Vladimir
  • 79
  • 1
  • 8
  • Try changing `isUser() {` to `isUser = () => {`. Otherwise you will need to bind `isUser` in your constructor. See [this](https://reactjs.org/docs/faq-functions.html#how-do-i-bind-a-function-to-a-component-instance) – Tom Jun 30 '21 at 18:56
  • (Can someone find the canonical dupe? That was the best I could do at the moment.) – Dave Newton Jun 30 '21 at 19:00

2 Answers2

1

When you do this:

onPress={this.isUser}

You're detaching isUser from the component's scope, and when it gets called on its own, "this" is undefined. You can fix it by creating an arrow function that just calls this.isUser():

onPress={() => this.isUser()}

or by making isUser itself an arrow function:

isUser = () => {
  ...
}

I've explained this in more detail elsewhere if you're interested in the specifics of how it's different and why it matters.

ray
  • 26,557
  • 5
  • 28
  • 27
1

In React class components you need to bind the function to have the correct this value. There are a few ways to do that, see here.

You could change your isUser declaration from:

isUser() {
  ...
}

To:

isUser = () => {
  ...
}

or you could bind it by adding a constructor like:

export class LogIn extends Component {
  constructor(props) {
    super(props);
    this.isUser = this.useUser.bind(this);
  }
  ...
}

Or you could bind the function directly in render, like this:

<MyButton
  name={'Log in'.toUpperCase()}
  onPress={this.isUser.bind(this)} />
Tom
  • 7,640
  • 1
  • 23
  • 47