繁体   English   中英

如何使用 Redux 在 Redux 中调度异步操作 Thunk:TypeError:无法读取未定义的属性“加载”

[英]How to dispatch async action in Redux using Redux Thunk: TypeError: Cannot read property 'loading' of undefined

我已经在 Redux 一侧设置了所有内容,并且我在 Redux Devtool 中看到了所有操作。 它工作得非常完美。 当我想在 React Component 中调度操作时会出现问题。 在登录组件中,我想调度操作,等待其响应,然后根据响应将其重定向到页面或显示错误。 这是我的代码:

userActions.js

import axios from "axios";
import {
  LOGIN_USER,
  LOGIN_USER_SUCCESS,
  LOGIN_USER_FAILED,
} from "./types";

const loginUserRequest = () => {
  return {
    type: LOGIN_USER,
  };
};

const loginUserSuccess = (user) => {
  return {
    type: LOGIN_USER_SUCCESS,
    payload: user,
  };
};

const loginUserFailed = (error) => {
  return {
    type: LOGIN_USER_FAILED,
    payload: error,
  };
};

export const loginUser = (dataSubmitted) => {
  return (dispatch) => {
    dispatch(loginUserRequest());
    axios
      .post("/api/users/login", dataSubmitted)
      .then((response) => {
        dispatch(loginUserSuccess(response.data));
      })
      .catch((err) => {
        dispatch(loginUserFailed(err));
      });
  };
};

userReducer.js:

import {
  LOGIN_USER,
  LOGIN_USER_SUCCESS,
  LOGIN_USER_FAILED,
} from "../actions/types";

const initialState = {
  loading: false,
  user: "",
  error: "",
};

export default function (state = initialState, action) {
  switch (action.type) {
    case LOGIN_USER:
      return { ...state, loading: true };

    case LOGIN_USER_SUCCESS:
      return { ...state, loading: false, user: action.payload, error: "" };

    case LOGIN_USER_FAILED:
      return { ...state, loading: false, user: "", error: action.payload };

    default:
      return state;
  }
}

上面的代码效果很好并且可以完成工作。 问题出在我正在调度异步操作的以下代码中。 运行代码后,我得到this.props.userData未定义。

登录.js

import React, { Component } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { loginUser } from "../../actions/userActions";

export class Login extends Component {
  state = {
    email: "",
    password: "",
    errors: [],
  };

  displayErrors = (errors) =>
    errors.map((error, i) => (
      <div className="alert alert-danger" key={i}>
        {error}
      </div>
    ));

  handleSubmit = (e) => {
    e.preventDefault();
    var { email, password } = this.state;
    var errors = [];

    if (email === "") {
      errors.push("Email is required");
    }

    if (password === "") {
      errors.push("Password is required");
    }

    this.setState({ errors: errors });
    //Problem occurs here
    this.props.dispatch(loginUser({ email, password }));

    if (response.payload.success) {
      sessionStorage.setItem("jwt", response.payload.token);
      sessionStorage.setItem("userId", response.payload._id);
      this.props.history.push("/");
    } else {
      errors.push("Username and/or Password is not correct");
      this.setState({ errors: errors });
    }
  };

  render() {
    return (
      <form className="form-signin" onSubmit={this.handleSubmit}>
        <h1 className="h3 mb-3 font-weight-normal">Sign in</h1>

        {this.state.errors.length > 0 && this.displayErrors(this.state.errors)}
        <label for="inputEmail" className="sr-only">
          Email address
        </label>
        <input
          type="email"
          id="inputEmail"
          className="form-control"
          placeholder="Email address"
          value={this.state.email}
          onChange={(e) => {
            this.setState({ email: e.target.value });
          }}
          required
          autoFocus
        />
        <label for="inputPassword" className="sr-only">
          Password
        </label>
        <input
          type="password"
          id="inputPassword"
          className="form-control"
          placeholder="Password"
          value={this.state.password}
          onChange={(e) => {
            this.setState({ password: e.target.value });
          }}
          required
        />
        <div className="checkbox mb-3">
          <label>
            <input type="checkbox" value="remember-me" /> Remember me
          </label>
        </div>
        <button
          className="btn btn-lg btn-primary btn-block"
          type="submit"
          onClick={this.handleSubmit}
        >
          Sign in
        </button>
        <Link to="/register">Sign Up</Link>
      </form>
    );
  }
}

function mapStateToProps(state) {
  return {
    userData: state.user,
  };
}

export default connect(mapStateToProps)(Login);

您需要安装connected-react-router以使用 redux 中的历史记录进行操作:

import { push } from 'connected-react-router';

export const loginUser = (dataSubmitted) => {
  return (dispatch) => {
    dispatch(loginUserRequest());
    axios
      .post("/api/users/login", dataSubmitted)
      .then((response) => {
        dispatch(loginUserSuccess(response.data));

        if (response.payload.success) {
          sessionStorage.setItem("jwt", response.payload.token);
          sessionStorage.setItem("userId", response.payload._id);
          push("/");
        } else {
          errors.push("Username and/or Password is not correct");
        }
      })
      .catch((err) => {
        dispatch(loginUserFailed(err));
      });
  };
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM