如何解决反应身份验证中的未捕获(承诺中)TypeError?

Posted

技术标签:

【中文标题】如何解决反应身份验证中的未捕获(承诺中)TypeError?【英文标题】:How to solve Uncaught (in promise) TypeError in react authentication? 【发布时间】:2019-11-08 09:38:02 【问题描述】:

我对 MERN 堆栈还很陌生。我正在尝试使用 jwt 设置用户身份验证。 仅当我使用前端登录时才会出现此问题。当我使用 POST man 发出 http 请求时,登录成功是成功的 但是,当我使用电子邮件和密码登录时,出现以下错误:

控制台

Uncaught (in promise) TypeError: Cannot read property 'data' of undefined
at authActions.js:40

我知道它显示了错误的位置,但我仍然无法修复它。

authActions.js

import axios from "axios";
import setAuthToken from "../utils/setAuthToken";
import jwt_decode from "jwt-decode";

import  GET_ERRORS, SET_CURRENT_USER, USER_LOADING  from "./types";

// Register User
export const registerUser = (userData, history) => dispatch => 
  axios
    .post("/api/users/register", userData)
    .then(res => history.push("/login")) // re-direct to login on successful register
    .catch(err =>
      dispatch(
        type: GET_ERRORS,
        payload: err.response.data
      )
    );
;

// Login - get user token
export const loginUser = userData => dispatch => 
  axios
    .post("/api/users/login", userData)
    .then(res => 
      // Save to localStorage

      // Set token to localStorage
      const  token  = res.data;
      localStorage.setItem("jwtToken", token);
      // Set token to Auth header
      setAuthToken(token);
      // Decode token to get user data
      const decoded = jwt_decode(token);
      // Set current user
      dispatch(setCurrentUser(decoded));
    )
    .catch(err =>
      dispatch(
        type: GET_ERRORS,
        payload: err.response.data
      )
    );
;

// Set logged in user
export const setCurrentUser = decoded => 
  return 
    type: SET_CURRENT_USER,
    payload: decoded
  ;
;

// User loading
export const setUserLoading = () => 
  return 
    type: USER_LOADING
  ;
;

// Log user out
export const logoutUser = () => dispatch => 
  // Remove token from local storage
  localStorage.removeItem("jwtToken");
  // Remove auth header for future requests
  setAuthToken(false);
  // Set current user to empty object  which will set isAuthenticated to false
  dispatch(setCurrentUser());
;

以下是我的登录前端代码。

login.jsx

class Login extends Component 
  constructor(props) 
    super(props);

    this.state = 
      email: "",
      password: ""
    ;
  
  componentDidMount() 
    // If logged in and user navigates to Login page, should redirect them to dashboard
    if (this.props.auth.isAuthenticated) 
      this.props.history.push("/dashboard");
    
  
  validateForm() 
    return this.state.email.length > 0 && this.state.password.length > 0;
  

  componentWillReceiveProps(nextProps) 
    if (nextProps.auth.isAuthenticated) 
      this.props.history.push("/dashboard"); // push user to dashboard when they login
    

    if (nextProps.errors) 
      this.setState(
        errors: nextProps.errors
      );
    
  

  handleChange = event => 
    this.setState(
      [event.target.id]: event.target.value
    );
  ;

  handleSubmit = event => 
    event.preventDefault();
    console.log("Submit called");
    const userData = 
      email: this.state.email,
      password: this.state.password
    ;

    this.props.loginUser(userData);
  ;

  render() 
    const errors = this.state;
    return (
      <div className="Login">
        <form onSubmit=this.handleSubmit>
          <FormGroup controlId="email" bs="large">
            <FormLabel>Email</FormLabel>
            <span className="red-text">errors.emailnotfound</span>
            <FormControl
              autoFocus
              type="email"
              value=this.state.email
              onChange=this.handleChange
              className=classnames("", 
                invalid: errors.email || errors.emailnotfound
              )
            />
          </FormGroup>
          <FormGroup controlId="password" bs="large">
            <FormLabel>Password</FormLabel>
            <span className="red-text">
              errors.password
              errors.passwordincorrect
            </span>
            <FormControl
              value=this.state.password
              onChange=this.handleChange
              type="password"
              className=classnames("", 
                invalid: errors.password || errors.passwordincorrect
              )
            />
          </FormGroup>
          <Button
            block
            bs="large"
            disabled=!this.validateForm()
            type="submit"
          >
            Login
          </Button>
          <br />
          <p> Dont have account ? </p>
          <Link to="/register">
            " "
            <p style= color: "blue" > Join Us </p>" "
          </Link>
        </form>
        <br />
      </div>
    );
  

我省略了一些导入语句来缩短代码。

【问题讨论】:

【参考方案1】:

错误在第 40 行,在payload: err.response.data

如果它说

无法读取未定义的属性“数据”

表示err.responsendefined

你应该在通过之前做一些检查。也许它返回了一个没有 .response 的不同错误。

试试console.log(err)看看里面有什么。

【讨论】:

试过控制台记录错误..它说Error InvalidTokenError: Invalid token specified: Cannot read property 'replace' of undefined【参考方案2】:

看起来您在发送数据之前没有对数据进行字符串化。需要 qs 库并将您的代码更改为:

axios
.post("/api/users/register", qs.stringify( userData ))
.then(res => history.push("/login")) // re-direct to login on successful register
.catch(err =>
  dispatch(
    type: GET_ERRORS,
    payload: err.response.data
  )
);

您还可以通过查看浏览器开发工具中的Network 选项卡来检查数据是否未正确发送。我希望以错误的格式发送数据。我希望我是正确的。

【讨论】:

不工作.. 我使用 JSON.stringify()。我收到Error Error: Request failed with status code 400【参考方案3】:

您需要从

更新您的代码

onSubmit=this.handleSubmitonSubmit=()=&gt;this.handleSubmit()

还有

onChange=this.handleChangeonChange=()=&gt;this.handleChange()

因此,您的密码和电子邮件未设置为状态,并且您的 API axios.post("/api/users/login", userData) 正在引发异常。

【讨论】:

不起作用..如果我改变函数调用方法,我输入时文本区域保持不变。 @arjun-kashyap 我已经更新了代码,请检查 我不认为这是问题所在。我控制台记录了用户数据,并将其设置为值 您的服务器似乎出现错误。您的服务器是否支持 cors 请求? 它确实..我添加了cors..当我使用Postman测试时,它是成功的

以上是关于如何解决反应身份验证中的未捕获(承诺中)TypeError?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决该错误>> WARN可能的未处理承诺拒绝(id:0):

反应:未捕获(承诺)错误:请求失败,状态码为 400

从 vuex 存储操作中的承诺返回错误

.catch() 甚至通过 fetch() 从另一个承诺中捕获所有错误

未捕获(承诺):错误:没有 AngularFireAuth 的提供者

护照后如何使用承诺登录。通过社会服务进行身份验证。 KeystoneJS + 护照