user12990369
user12990369

Reputation:

Have to Click link Twice in order for Link to work

I'm kinda new to react and having trouble creating an authentication application.

Whenever I click login, I need to click on the Login Link twice in order for me to login. And after whenever I login by pressing login twice i get directed to my home component but, I get a warning message:

Can't perform a React state update on an unmounted component.

This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

Im wondering where I went wrong with my code.

Heres a snip of my login.js.

import React, { Component } from 'react';
import { Link } from 'react-router-dom';

class Login extends Component {
    constructor(props){
        super(props);
        this.state = {
            login: false,
        }
    }


    checkUser(event){
        event.preventDefault();
        let data= {
            email: this.refs.email.value,
            password: this.refs.password.value,
        }
        var request = new Request('http://localhost:3001/api/login', {
            method: 'POST', 
            headers: new Headers({ 'Content-Type' : 'application/json' }),
            body: JSON.stringify(data)
        });

        fetch(request).then((response) => {
            response.json().then((data) => {
                //console.log(data.value);
                this.setState({login: data.value});
            })
        }).catch(function(err){
            console.log(err)
        });
    }

    render (){
        console.log(this.state.login);
        const linkTo = this.state.login ? "/home" : "/login"
        console.log(linkTo);
        return (
            <div> 
                <form>
                    <label>Email</label>
                    <input type="text" ref="email" placeholder="Email"></input>
                    <label>Password</label>
                    <input type="password" ref="password" placeholder="Password"></input>
                    <button onClick = {this.checkUser.bind(this)}>
                        <Link to={linkTo}>Login</Link>
                    </button>
                </form>
                <p>Dont have an account? <Link to="/register">Register</Link></p>
            </div>
        )
    }
}

the console shows the /home when I login correctly but the my page doesn't render, so I need to press the button again.

Any help would be appreciated.

Upvotes: 1

Views: 2054

Answers (2)

Advait Junnarkar
Advait Junnarkar

Reputation: 3705

Your logic isn't clear. Initially you assume that the user isn't logged in, if you know this for certain then you shouldn't need to call checkUser. However, because you're not sure you are calling your login API - or perhaps this is the only call to your login API?

The best choice would be to remove <Link to={linkTo}>Login</Link> and const linkTo = this.state.login ? "/home" : "/login"

Then inside checkUser on a successful login programatically navigate to /login:

this.props.history.push('/login')

OR

render() {
  if (this.state.login) return <Redirect to="/login" />;
  ...
}

You can put the link anywhere else. Just don't wrap it in a button, as that functionality will conflict with the function attached to your button. Avoid wrapping links in buttons or vice versa, just in plain HTML their functionality is separate and will conflict.

Do one or the other:

  1. Style a link to look like a button, or
  2. If you really need to navigate using a button do it programmatically - generally it's not good for SEO. But for a login form it's fine.

Upvotes: 1

i.brod
i.brod

Reputation: 4603

Your entire logic there is very problematic. Your button needs to trigger the login process, and nothing else. It cant both be a "login" button, and a link. After the login is complete, you can manually redirect to wherever you want. For instance:

fetch(request).then((response) => {
            response.json().then((data) => {
                //Do some checking if the login is successful..
                //if it is, redirect:
                this.props.history.push('/home')
            })
        }).catch(function(err){
            console.log(err)
        });

The button:

<button onClick = {this.checkUser.bind(this)}>Login</button>

Upvotes: 1

Related Questions