处理前端的后端错误状态

时间:2019-08-02 10:58:29

标签: reactjs firebase validation authentication error-handling

如果电子邮件和密码为空,我们的后端开发人员将发送

{
    "errors": {
        "email": "please enter valid emails",
        "password": "please enter password"
    }
}

,如果电子邮件和密码与数据库不匹配 general: "email or password not match"

第一种情况,他在第二个对象内部发送数据,我该如何在前端处理呢?

这是我用于检查文本框验证的代码

exports.validateLoginData = (data) => {
      let errors = {};
      if (isEmpty(data.email)) errors.email = 'please enter valid emails';
      if (isEmpty(data.password)) errors.password = 'please enter password';
     return {
         errors,
         valid: Object.keys(errors).length === 0 ? true : false
     }
}

这是我的登录后端的代码

exports.login = (req, res) => {
    const user = {
        email: req.body.email,
        password: req.body.password
    };

    const {valid,errors} = validateLoginData(user);
    if(!valid) return res.status(400).json({errors});

    firebase.auth().signInWithEmailAndPassword(user.email, user.password)
        .then((data) => {
            return data.user.getIdToken();
        })
        .then((token) => {
            return res.json({
                token
            });
        })
        .catch((err) => {
            console.error(err);
            if (err.code === 'auth/wrong-password') {
                return res.status(403).json({
                    general: 'email or password not match'
                })
            } else {
                return res.status(500).json({
                    error: err.code
                })
            }

        })
}

这是我的登录页面js代码

import React, { Component } from 'react'
import { withStyles } from '@material-ui/styles';
import PropTypes from 'prop-types'
import AppIcon from '../images/icon.png'
//mivi stuff
import Grid from '@material-ui/core/Grid';
import  Typography  from '@material-ui/core/Typography';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import axios from 'axios';

const styles = {
    form:{
        textAlign: 'center'
    },
    image:{
        margin: '20px auto 20px auto'
    },
    pagetitle:{
        margin: '10px auto 10px auto'
    }, 
    textfeild:{
        margin: '10px auto 10px auto'
    },
    button:{
        marginTop: 20
    },
    customerror:{
        color:'red',
        fontSize:'0.8rem'
    }
};




class login extends Component {
    constructor() {
        super();
        this.state = {
            email: '',
            password: '',
            loading: false,
            errors: {}
        }
    }
    handleChnage = (event) => {
        this.setState({
            [event.target.name]: event.target.value
        })
    }
    handleSubmit = (event) => {
        // console.log('hi');
        event.preventDefault();
        this.setState({
            loading: true
        });
        const userData = {
            email: this.state.email,
            password: this.state.password
        }
        axios.post('/login', userData)
            .then((res) => {
                //console.log(res.data)
                this.setState({
                    loading: false
                });
                this.props.history.push('/');
            })
            .catch((err) => {
                console.log(err.response.data)

                this.setState({
                    errors: err.response.data.errors,
                    loading: false
                })
            })
    }
    render() {
        const { classes } = this.props;
        const { errors, loading,} = this.state;
        return (
            <Grid container className={classes.form}>
                <Grid item sm />
                <Grid item sm >
                    <img src={AppIcon} alt="app cion" className={classes.image} />
                    <Typography variant="h2" className={classes.pagetitle}>Login</Typography>
                    <form noValidate onSubmit={this.handleSubmit}>
                        <TextField id="email" name="email" type="email" label="Email" className={classes.textfeild}
                            helperText={errors.email} error={errors.email ? true : false} value={this.state.email} onChange={this.handleChnage} fullWidth />
                        <TextField id="password" name="password" type="password" label="Password" className={classes.textfeild}
                            helperText={errors.password} error={errors.password ? true : false} value={this.state.password} onChange={this.handleChnage} fullWidth />
                        {errors.general &&(
                            <Typography variant="body2" className={classes.customerror}>
                                {errors.general}
                            </Typography>
                        )}
                        <Button type="submit" variant="contained" color="primary" className={classes.button}>Login </Button>
                    </form>
                </Grid>
                <Grid item sm />
            </Grid>
        )
    }
}

login.propTypes = {
    classes: PropTypes.object.isRequired
}

export default withStyles(styles)(login);

这里什么时候 单击登录按钮,而无需输入电子邮件和密码,其显示验证错误

但是电子邮件和密码为空,然后单击“登录”按钮抛出错误

  

TypeError:错误未定义

 helperText={errors.email} error={errors.email ? true : false} value={this.state.email} onChange={this.handleChnage} fullWidth />

但是在控制台中,我记录了错误状态

general: "email or password not match"

我的问题是

helperText={errors.email} error={errors.email ? true : false}仅用于验证,如果其空白仅会显示错误,但是如果有任何数据输入并单击“登录”,则此行会出现错误

1 个答案:

答案 0 :(得分:1)

如果我正确地理解了这一点,那么您的情况就是,第一次加载组件,而没有输入emailpassword的情况下,您按了login按钮,并且按预期得到了错误。

但是第二次输入emailpassword,然后这次按下login按钮也会出错。

这是因为,当emailpassword字段为空时,您第一次设置了错误状态。现在,当您键入内容然后按login时,您以前的状态保持原样,结果是出现错误。您需要在第二次点击之前清除错误状态。

您可以在handleSubmit之类的API调用之前清除错误状态,

let errors = {email:'',password:''} //define empty error state 
this.setState({
    loading: true,
    errors      //reset error state
});