如何在mern应用程序中实现登录功能?

ugmeyewa  于 2021-10-10  发布在  Java
关注(0)|答案(1)|浏览(412)

我正在本地主机上开发一个(易于使用的)记笔记web应用程序(前端端口3000,后端端口5000)。我在实现用户登录功能时遇到问题。我将在这里设法提炼出这个问题。
我的主app.jsx组件作为子组件有一个loginscreen.jsx组件,如下所示:

import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import AuthService from '../services/auth.js';
import './LoginScreen.css';

const LoginScreen = ({ history }) => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');

  useEffect(() => {
    if (localStorage.getItem('authToken')) history.push('/');
  }, [history]);

  const loginHandler = async e => {
    e.preventDefault();

    try {
      const data = { email, password };

      AuthService.loginUser(data).then(response => {
        localStorage.setItem('authToken', response.data.token);
      });

      history.push('/');
    } catch (error) {
      setError(error.response.data.error);

      setTimeout(() => {
        setError('');
      }, 5000);
    }
  };

  return (
    <div className="login-screen">
      <form
        className="login-screen__form"
        onSubmit={loginHandler}
        autoComplete="off"
      >
        <h3 className="login-screen__title">Login</h3>
        {error && <span className="error-message">{error}</span>}

        <div className="form-group">
          <label htmlFor="email">Email:</label>
          <input
            type="email"
            required
            id="email"
            placeholder="enter email"
            value={email}
            onChange={e => setEmail(e.target.value)}
            tabIndex={1}
          />
        </div>

        <div className="form-group">
          <label htmlFor="password">
            Password:{' '}
            <Link
              to="/forgotpassword"
              className="login-screen__forgotpassword"
              tabIndex={4}
            >
              Forgot Password?
            </Link>
          </label>
          <input
            type="password"
            required
            id="password"
            placeholder="enter password"
            value={password}
            onChange={e => setPassword(e.target.value)}
            tabIndex={2}
          />
        </div>

        <button type="submit" className="btn btn-primary" tabIndex={3}>
          Login
        </button>
        <span className="login-screen__subtext">
          Don't have an account? <Link to="/register">Register</Link>
        </span>
      </form>
    </div>
  );
};

export default LoginScreen;

当用户单击“登录”时,应触发authservice,如下所示:

import http from '../routing/http-auth.js';

class AuthService {
  loginUser = data => http.post('/login', data);

  registerUser = data => http.post('/register', data);

  userForgotPassword = data => http.post('/forgotpassword', data);

  userPasswordReset = data => http.put('/passwordreset/:resetToken', data);
}

export default new AuthService();

上面文件中的http是一个axios示例,如下所示。

import axios from 'axios';

export default axios.create({
  baseURL: 'http://localhost:5000/api/v1/auth',
  headers: {
    'Content-type': 'application/json'
  }
});

因此,请求被路由到后端,在这里:

import express from 'express';
import AuthController from './auth.controller.js';

const router = express.Router();

router.route('/register').post(AuthController.register);
router.route('/login').post(AuthController.login);
router.route('/forgotpassword').post(AuthController.forgotPassword);
router.route('/passwordreset/:resetToken').put(AuthController.passwordReset);

export default router;

然后这里:

static login = async (req, res, next) => {
    const email = req.body.email;
    const password = req.body.password;

    if (!email || !password) {
      return next(
        new ErrorResponse('please provide an email and password', 400)
      );
    }

    try {
      const user = await User.findOne({ email }).select('+password');

      if (!user) return next(new ErrorResponse('invalid credentials', 401));

      const isMatch = await user.matchPasswords(password);

      if (!isMatch) return next(new ErrorResponse('invalid credentials', 401));

      sendToken(user, 200, res);
    } catch (error) {
      next(error);
    }
  };

这一切都在一个虚拟应用程序上起作用,但现在,它在我的笔记应用程序中不起作用。我得到一个错误:

Uncaught (in promise) TypeError: Cannot read property 'data' of undefined
    at loginHandler (LoginScreen.jsx:27)

我怎样才能做到这一点?

fhg3lkii

fhg3lkii1#

你的 TypeError: Cannot read property 'data' of undefined 表示您的代码试图读取 .data 来自未定义(null,缺少)对象的属性。
在第27行,您的代码执行以下操作: setError(error.response.data.error); 因此,您的错误消息意味着 error 存在但 error.response 没有。
console.log(error) 就在第27行之前(或设置断点),这样您就可以确保理解 error 你抓住的物体。
如果错误消息说 TypeError: Cannot read property 'data' of an undefined object named error.response . 但事实并非如此,所以你必须自己做出推断。

相关问题