Отображение ответа бэкэнда в виде сообщения для реагирования на компонент внешнего интерфейса - PullRequest
1 голос
/ 22 апреля 2020

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

Вот функция контроллера входа:

 loginUser: async (req, res, next) => {
    try {
      console.log("inside login controller")
      const { email, password } = req.body
      if (!email || !password) {
        return res.status(400).json({ message: "Email and password are must" })
      }
      if (!validator.isEmail(email)) {
        return res.status(400).json({ message: "Invalid email" })
      }
      const user = await User.findOne({ email })
      if (!user) {
        return res.status(404).json({ message: "This email does not exist" })
      }
      if (!user.confirmPassword(password)) {
        // console.log("Password in login controller", password)
        return res.status(401).json({ message: "Incorrect password" })
      }

      res.status(200).json({ user })
    } catch (error) {
      return next(error)
    }
  }

И компонент входа выглядит так:

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

class LoginForm extends Component {
  constructor(props) {
    super(props)
    this.state = {
      email: "",
      password: "",
    }
  }

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

  handleSubmit = (event) => {
    event.preventDefault()
    const { email, password } = this.state

    const loginData = {
      email: this.state.email,
      password: this.state.password,
    }

    if (!email || !password) {
      return toastError("Email and password are must.")
    }

    if (password.length < 6) {
      return toastError("Password must contain 6 characters.")
    }

    if (!validator.isEmail(email)) {
      return toastError("Invalid email.")
    }

    this.props.dispatch(
      loginUser(loginData, () => this.props.history.push("/"))
    )
  }

  render() {
    const isAuthInProgress = this.props.auth.isAuthInProgress
    return (
      <div>
        <div className="field">
          <p className="control has-icons-left has-icons-right">
            <input
              className="input"
              onChange={this.handleChange}
              name="email"
              value={this.state.email}
              type="email"
              placeholder="Email"
            />
            <span className="icon is-small is-left">
              <i className="fas fa-envelope"></i>
            </span>
          </p>
        </div>
        <div className="field">
          <p className="control has-icons-left">
            <input
              className="input"
              onChange={this.handleChange}
              name="password"
              value={this.state.password}
              type="password"
              placeholder="Password"
            />
            <span className="icon is-small is-left">
              <i className="fas fa-lock"></i>
            </span>
          </p>
        </div>
        <div className="field">
          <p className="control">
            {isAuthInProgress ? (
              <button className="button is-success is-loading">Login</button>
            ) : (
              <button onClick={this.handleSubmit} className="button is-success">
                Login
              </button>
            )}
          </p>
        </div>
        <Link to="/forgot-password">
          <p className="has-text-danger">Forgot password?</p>
        </Link>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return state
}

export default connect(mapStateToProps)(LoginForm)

действие при входе в систему

export const loginUser = (loginData, redirect) => {
  return async (dispatch) => {
    dispatch({ type: "AUTH_STARTS" })
    try {
      const res = await axios.post(`${baseUrl}/users/login`, loginData)
      console.log(res.data)
      dispatch({
        type: "AUTH_SUCCESS",
        data: { user: res.data.user }
      })
      localStorage.setItem("authToken", res.data.token)
      redirect()
      toastSuccess("You are now logged in!")
    } catch (err) {
      console.log
      dispatch({
        type: "AUTH_ERROR",
        data: { err },
      })
    }
  }
}

Редуктор авторизации

const auth = (state = initialState, action) => {
  switch (action.type) {
    case "AUTH_STARTS":
      return {
        ...state,
        isAuthInProgress: true,
        isAuthenticated: false,
        authError: null,
      }

    case "AUTH_SUCCESS":
      return {
        ...state,
        isAuthInProgress: false,
        authError: null,
        isAuthenticated: true,
        isIdentifyingToken: false,
        user: action.data.user,
      }

    case "AUTH_ERROR":
      return {
        ...state,
        isAuthInProgress: false,
        authError: action.data.error,
        isAuthenticated: false,
        user: {},
      }

Также есть необходимость в подобных проверках, как я делал и в контроллере, и в компонентах, таких как if (!email || !password) и if (!validator.isEmail(email)). Или это должно быть только в бэкэнде?

1 Ответ

1 голос
/ 22 апреля 2020

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

handleSubmit = (event) => {
  /* your-validation-code */
  this.props.dispatch(loginUser(loginData, this.checkForLoginError()));
};

checkForLoginError = () => {
  const authenticationError = this.props.auth.authError;
  if (authenticationError === null) {
    this.props.history.push("/");
  } else {
    return toastError(authenticationError);
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...