Как отправить данные ответа от api на действие в React Redux? - PullRequest
2 голосов
/ 26 мая 2020

В настоящее время я работаю над проектом электронной коммерции, и мы используем react-redux. Но у меня возникла проблема с возвратом ответа от экземпляров API с использованием вызова Ax ios request для действия для входа с модулем Jwt.

Это файл Ax ios, который состоит из базовых URL-адресов и экземпляров .

api / lib / ax ios. js:

/* eslint-disable no-nested-ternary */
import axios from "axios"
import { store } from "../../redux/store"
import { REFRESH_TOKEN } from "../../redux/auth/constant"
import Environment from "./environment"

const axiosInstance = axios.create({
  baseURL: Environment.BASE_URL,
  headers: {
    Authorization: localStorage.getItem("access")
      ? `JWT${localStorage.getItem("access")}`
      : "none",
    "Content-Type": "application/json",
    accept: "application/json"
  }
})

axiosInstance.interceptors.response.use(
  (response) => response,
  (error) => {
    const originalRequest = error.config

    if (
      error.response.status === 401 &&
      error.response.statusText === "Unauthorized"
    ) {
      const body = store.getState().auth.token.refresh
      return axiosInstance
        .post("api/token/refresh/", { refresh: body })
        .then((response) => {
          store.dispatch({
            type: REFRESH_TOKEN,
            payload: response.data
          })
          axiosInstance.defaults.headers.Authorization = `JWT ${response.data.access}`
          originalRequest.headers.Authorization = `JWT ${response.data.access}`

          return axiosInstance(originalRequest)
        })
    }
    return Promise.reject(error)
  }
)

export default axiosInstance

Здесь также находится файл среды, в котором хранятся все наши переменные среды.

api / lib / environment. js:

const Environment = {
  BASE_URL: "http://babylandworld.com:8000/"
}

export default Environment

Я вызываю запрос API из файла аутентификации внутри api / lib / auth как:

api / lib / auth. js:

/* eslint-disable import/prefer-default-export */
import axiosInstance from "./axios"
// Auth Request from backend api using axios
const auth = async (username, password) => {
  const body = { username, password }
  const response = await axiosInstance
    .post(`/api/token/obtain/`, body)
    .then((res) => {
      axiosInstance.defaults.headers.Authorization = `JWT ${res.data.access}`
    })
  return response
}
export { auth }

Я отправил ответ из файла api / auth. js в auth / action. js. Но я получаю сообщение об ошибке при отправке и отлове без пользовательских данных после отправки формы входа.

Вот действие. js код: auth / action. js:

import * as constants from "./constant"

import { auth } from "../../api/lib/auth"

const loginBegin = () => ({
  type: constants.LOGIN_BEGIN
})
const login = ({ username, password }) => (dispatch) => {
  dispatch({
    type: constants.LOGIN_SUCCESS,
    paylaod: auth(username, password).data
  }).catch(() =>
    dispatch({
      type: constants.LOGIN_FAIL
    })
  )
}

export { loginBegin, login }

Кроме того, я создал типы действий в константе. js файл как:

auth / constant. js:

export const REFRESH_TOKEN = "REFRESH_TOKEN"
export const LOGIN_BEGIN = "LOGIN_BEGIN"
export const LOGIN_SUCCESS = "LOGIN_SUCCESS"
export const LOGIN_FAIL = "LOGIN_FAIL"
export const AUTH_ERROR = "AUTH_ERROR"
export const LOGOUT_SUCCESS = "LOGOUT_SUCCESS"

Вот файл-редуктор: auth / reducer. js:

import { actions } from "react-table"
import * as constants from "./constant"

const initialState = {
  token: localStorage.getItem("token"),
  isAuthenticated: null,
  isLoading: false,
  user: null
}
function authReducer(state = initialState, action) {
  switch (action.type) {
    case constants.LOGIN_BEGIN:
      return {
        ...state,
        isAuthenticated: false,
        isLoading: true,
        user: ""
      }
    case constants.LOGIN_SUCCESS:
      return {
        ...state,
        ...action.payload,
        isAuthenticated: true,
        isLoading: false
      }
    case constants.LOGIN_FAIL:
    case constants.LOGOUT_SUCCESS:
      return {
        ...state,
        token: null,
        isAuthenticated: false,
        user: null,
        isLoading: false
      }
    default:
      return state
  }
}
export default authReducer

Это наш компонент страницы входа как: pages / auth / loginTabset. js:

/* eslint-disable jsx-a11y/anchor-has-content */
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, { Component } from "react"

import PropTypes from "prop-types"
import { connect } from "react-redux"
import { Redirect } from "react-router-dom"
import { login } from "../../redux/auth/action"

export class LoginTabset extends Component {
  state = {
    username: "",
    password: ""
  }

  clickActive = (event) => {
    document.querySelector(".nav-link").classList.remove("show")
    event.target.classList.add("show")
  }

  handleSubmit = (e) => {
    e.preventDefault()
    this.props.login(this.state.username, this.state.password)
  }

  handleChange = (e) => this.setState({ [e.target.name]: e.target.value })

  render() {
    if (this.props.isAuthenticated) {
      return <Redirect to="/dashboard" />
    }
    const { username, password } = this.state
    return (
      <div>
        <h4 className="text-center">Login Panel</h4>
        <hr />
        <form
          className="form-horizontal auth-form"
          onSubmit={this.handleSubmit}>
          <div className="form-group">
            <input
              required=""
              name="username"
              value={username}
              type="text"
              className="form-control"
              placeholder="Username"
              id="username"
              onChange={this.handleChange}
            />
          </div>
          <div className="form-group">
            <input
              required=""
              name="password"
              value={password}
              type="password"
              className="form-control"
              placeholder="Password"
              id="password"
              onChange={this.handleChange}
            />
          </div>
          <div className="form-terms">
            <div className="custom-control custom-checkbox mr-sm-2">
              <input
                type="checkbox"
                className="custom-control-input"
                id="customControlAutosizing"
              />
              <label className="d-block" htmlFor="chk-ani2">
                <input
                  className="checkbox_animated"
                  id="chk-ani2"
                  type="checkbox"
                />
                Reminder Me{" "}
                <span className="pull-right">
                  {" "}
                  <a href="#" className="btn btn-default forgot-pass p-0">
                    lost your password
                  </a>
                </span>
              </label>
            </div>
          </div>
          <div className="form-button">
            <button className="btn btn-primary" type="submit">
              Login
            </button>
          </div>
          <div className="form-footer">
            <span>Or Login up with social platforms</span>
            <ul className="social">
              <li>
                <a className="fa fa-facebook" href="" />
              </li>
              <li>
                <a className="fa fa-twitter" href="" />
              </li>
              <li>
                <a className="fa fa-instagram" href="" />
              </li>
              <li>
                <a className="fa fa-pinterest" href="" />
              </li>
            </ul>
          </div>
        </form>
      </div>
    )
  }
}
LoginTabset.propTypes = {
  login: PropTypes.func.isRequired,
  isAuthenticated: PropTypes.bool.isRequired
}

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated
})
export default connect(mapStateToProps, { login })(LoginTabset)

Проблема: при отправке формы входа возникает ошибка при отправке действия из api / lib / auth и отсутствие данных ответа от сервера API .

Пожалуйста, любой, помогите как можно скорее решить эту проблему.

1 Ответ

1 голос
/ 26 мая 2020
Функция

dispatch не возвращает вам обещание использовать. Вместо этого вы должны вызвать функцию аутентификации и дождаться ее перед запуском отправки, поскольку это асинхронная c функция.

Вы можете использовать asyn c -await с try catch, как показано ниже

const login = ({ username, password }) =>async (dispatch) => {

  try {
     const res = await auth(username, password);
     dispatch({
       type: constants.LOGIN_SUCCESS,
       paylaod: res.data,
     })
  } catch(error ) {
    dispatch({
      type: constants.LOGIN_FAIL
    });
  }
}

export { loginBegin, login }
...