Не уверен, почему мой логин не работает, если он не совмещен с предыдущей регистрацией - PullRequest
1 голос
/ 14 июля 2020

Итак, я пытаюсь понять, почему я получаю указанную ниже ошибку при входе в систему существующего пользователя. В правой части панели навигации должно отображаться имя вошедшего в систему пользователя. Это странно, потому что, когда я впервые регистрирую нового пользователя, а затем сразу же после этого вхожу в систему, у меня нет проблем (я вхожу в систему, и имя отображается на панели навигации).

Я надеюсь, что приведенный ниже код не является излишним но я просто не знаю, где именно ошибка. Пожалуйста, дайте мне знать, если вам понадобится дополнительная информация для лучшего обзора.

TypeError: Cannot read property 'username' of null
Navbar.handleUser
C:/Users/charl/Desktop/IRONHACK/Week-9/finalproject/client/src/components/Navbar.js:23
  20 | 
  21 |    handleUser(user){
  22 |        const theLoggedUser = getUser(user)
> 23 |        return theLoggedUser.username
     | ^  24 |    }
  25 | 
  26 |    // handleUserImage(user){

Uncaught (in promise) DOMException: Failed to execute 'open' on 'XMLHttpRequest': Invalid URL
    at dispatchXhrRequest (http://localhost:3001/static/js/1.chunk.js:10179:13)
    at new Promise (<anonymous>)
    at xhrAdapter (http://localhost:3001/static/js/1.chunk.js:10162:10)
    at dispatchRequest (http://localhost:3001/static/js/1.chunk.js:10785:10)

index.js:1 Warning: 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.
    in Login (created by Context.Consumer)
    in Route (at App.js:24)
    in Switch (at App.js:19)
    in div (at App.js:17)
    in App (at src/index.js:10)
    in Router (created by BrowserRouter)
    in BrowserRouter (at src/index.js:9)

Navbar. js

import React from "react";
import './Navbar.css';
import {Link} from "react-router-dom";
// import {logout, getUser} from "../utils/auth";
import {logout, getUser} from "../utils/auth";
// const { getUser } = require("../utils/auth"); 

class Navbar extends React.Component {
    constructor() {
        super()

        this.state = {
            
        }
    }

    handleLogout(user){
        logout(user)
    }

    handleUser(user){
        const theLoggedUser = getUser(user)
        return theLoggedUser.username
    }

    // handleUserImage(user){
    //     const theLoggedUser = getUser(user)
    //     return theLoggedUser.imageUrl
    // }

    // handleUserLocation(user){
    //     const theLoggedUser = getUser(user)
    //     return theLoggedUser.location
    // }

    render() {
        return (
            <nav className="navcontainer">
                <Link to="/allchallenges"><img className="logostreet" src="/images/logo.png" alt="logo" /></Link>
                <Link to="/allchallenges"><strong>All challenges</strong></Link>
                <Link to="/startchallenge"><strong>Start a challenge</strong></Link>
                <Link to="/profile"><strong>Profile settings</strong></Link>
                <Link to="/friends"><strong>Community</strong></Link>
                <Link to="/about"><strong>About</strong></Link>
                <Link to="/todo"><strong>To-do</strong></Link>
                <Link to="/" onClick={this.handleLogout}><strong>Log out</strong></Link>
                <p className="welcomemessage">{this.handleUser()}</p>
                {/* <p className="welcomemessage">Welcome {this.handleUserLocation()}</p> */}
                {/* <p className="welcomemessage">Welcome {this.handleUserImage()}</p> */}
            </nav>            
        )
    }
}

export default Navbar

Логин. js

import React from 'react'
import Footer from "../components/Footer"
import Warning from "../components/Warning"
import "./Login.css"
import { login } from '../utils/auth'

class Login extends React.Component {
    constructor() {
        super()

        this.handleChange = this.handleChange.bind(this)
        this.handleFormSubmit = this.handleFormSubmit.bind(this)

        this.state = {
            user: { // remove?
                username: "",
                password: ""    
            }
        }
    }

    handleChange(event){
        event.preventDefault()
        let userCopy = {...this.state.user}
        userCopy[event.target.name] = event.target.value
        this.setState({
            user: userCopy
        })
    }

    handleFormSubmit(event){
        event.preventDefault()
        login(this.state.user)
        .then((response) => {
                console.log("You log in")
                this.setState({
                    error: null
                }, () => {
                    console.log("You log in 2")
                    this.props.history.push("/allchallenges")
                })
            } 
        )
        .catch((error) => {
            console.log("You don't log in")
            this.setState({error: error.response && error.response.data})
        })
    }

    render() {
        return (
            <div className="loginpage">
                <Warning/>
                <h1>Login and start challenging your friends!</h1>
                <h2>Show us what you got!</h2>
                
                <form className="formcontainerlogin" onSubmit={this.handleFormSubmit}>
                    <div className="userpart">
                        <label className="userlabel">First name:</label><br></br>
                        <input className="userform" type="text" name="username" value={this.state.username} placeholder="What was your username again?" onChange={(event) => this.handleChange(event)}></input>
                    </div>

                    <div className="passwordpart">
                        <label className="passwordlabel">Password:</label><br></br>
                        <input className="passwordform" type="password" name="password" value={this.state.password} placeholder="We bet you forgot your password again..." onChange={(event) => this.handleChange(event)}></input>
                    </div>
                    <button className="loginbutton">Log in</button>
                </form>
                
                <img className="pictureplank" src="/images/corn.jpg" alt="plankingpic" />
                
                <Footer/>
            </div>
        )
    }
}

export default Login

авт. js

import Axios from "axios"
import qs from "qs"

const axios = Axios.create({
    baseURL: `${process.env.REACT_APP_API_BASE}/`,
    withCredentials: true,
    headers: {"content-type": "application/x-www-form-urlencoded"}
})

//signup
export const signup = (user) => {
    return axios({
      method: "POST",
      url: "signup",
      data: qs.stringify(user)  
    })
    .then((response) => {
        setUser(response.data)
    })
    .catch((error) => {
        console.log(error)
    })
}

//login
export const login = (user) => {
    return axios({
        method: "POST",
        url: "login",
        data: qs.stringify(user)
    })
    .then((response) => {
        getUser(response.data)
        // setUser(response.data.user)
        // getUser(response.data)
    })
    .catch((error) => {
        console.log(error)
    })
} 

//setUser
export const setUser = (user) => {
    window.localStorage.setItem("user", JSON.stringify(user))
    console.log("user has been SET out of local storage")
}

//getUser
export const getUser = (user) => {
    console.log("user has been GET out of local storage (just before)")
    return JSON.parse(window.localStorage.getItem("user"))
}

//logout
export const logout = (user) => {
    window.localStorage.removeItem("user")
    console.log("user has been logged out of local storage")
}

индекс. js (бэкэнд)

var express = require('express');
var router = express.Router();
var User = require("../models/usermodel");
var Challenge = require("../models/challengemodel");
var Todo = require("../models/todomodel");
var Response = require("../models/responsemodel");
const bcrypt = require("bcrypt");
// const uploader = require('../configs/cloudinary-setup')
// import { getUser } from '../utils/auth'
// const { getUser } = require('../utils/auth'); 

//signup
router.post("/signup", (req,res) => {
  User
  .findOne({"username": req.body.username})
  .then(user => {
    if(user != null) {
      console.log("Charles change the username")
      res.json(user, {
        errorMessage: "This username is already being used! Please use another one."
      })
    } else {
      bcrypt.hash(req.body.password,10,function(err,hash){
        User
        .create({
          username: req.body.username,
          password: hash
        })
        .then(response => {
          res.json(response)
        })
        .catch(error => {
          res.json(error)
        })
      })
    }
  })
  .catch(error => {
    console.log("error has happened", error)
  })
})

//login
router.post("/login", (req,res) => {
  User
  .findOne({"username": req.body.username})
  .then(user => {
    if(!user) {
      res.send("This user does not exist!")
      console.log("Charles the user doesn't exist")
    } else {
      bcrypt.compare(req.body.password, user.password, function(err,result) {
        if(!result) {
          res.json({message: "incorrect credentials"})
        } else {
          req.session.currentUser = user
          res.json("Logged in")
        }
      }) 
    }
  })
  .catch(error => {
    res.json({message: error})
  })
})

Ответы [ 2 ]

1 голос
/ 15 июля 2020

Предложение

Обновите следующий код, причину см. В комментарии.

// Navbar.js
// handleUser
  handleUser(user) {
    const theLoggedUser = getUser(user);
    return theLoggedUser.username || "Guest"; // Incase user is not logged in. You can do something fancier here
  }

  // Auth.js
  //getUser
  export const getUser = user => {
    console.log("user has been GET out of local storage (just before)");
    return JSON.parse(window.localStorage.getItem("user")) || {}; // Return an empty object in case localstorage is empty for given key
  };


// auth.js - Note: Uncomment the setUser method in login method
    //login
    export const login = (user) => {
        return axios({
            method: "POST",
            url: "login",
            data: qs.stringify(user)
        })
        .then((response) => {
            setUser(response.data.user) // this line need to be uncommented like this
        })
        .catch((error) => {
            console.log(error)
        })
    } 
0 голосов
/ 14 июля 2020

В функции handleUser он пытается получить пользователя из локального хранилища, а затем возвращает его имя пользователя:

    handleUser(user){
        const theLoggedUser = getUser(user)
        return theLoggedUser.username
    }

Если ни один пользователь не вошел в систему, в локальном хранилище нет пользователя, поэтому getUser, по-видимому, возвращает значение null.

Поскольку это нормальная и ожидаемая ситуация, вы должны добавить в handleUser условие, что делать, если не было входа в систему.

Единственное место, где я вижу этот вызов, - это

                <p className="welcomemessage">{this.handleUser()}</p>

Так что, возможно, он вернет «Пожалуйста, войдите в систему» ​​или null, если getUser вернет null?

...