首页 > 解决方案 > 对于无状态 React 表单(客户端和服务器错误)的最佳错误处理流程是什么?

问题描述

我添加了整个组件,因为我是新手,所以我认为更多信息总比不够好。基本上它所在的表格是“无状态的”,除了使用表格本身持有的状态。我正在尝试处理来自两个角度的错误。客户端错误,例如“密码不匹配”、“不是有效的电子邮件”等。我正在尝试使用验证器库。第二个角度是服务器端错误。目前错误将来自我的突变响应。我我希望我能找到一种在没有状态的情况下处理这些错误的平滑方法,目前我将尝试为客户端使用 handleChange 函数。如果这是一种不好的方法或数据量很大,请分享您的建议/智慧。此外,任何建议或代码中非常感谢更好的实践,并在以后的发布中。谢谢(对全栈开发非常陌生)

进口

import React from 'react'
import Container from '@material-ui/core/Container'
import { makeStyles } from '@material-ui/core/styles'
import TextField from '@material-ui/core/TextField'
import Button from '@material-ui/core/Button'
import Paper from '@material-ui/core/Paper'
import gql from 'graphql-tag'
import { useMutation } from '@apollo/react-hooks'
import FormHelperText from '@material-ui/core/FormHelperText'
import validate from 'validate.js'
import FormControl from '@material-ui/core/FormControl'

用于样式的材质 UI

const useStyles = makeStyles({
  form: {
    width: '100%',
    marginTop: 15,
  },
  paper: {
    marginTop: 15,
  },
  register: {
    margin: 15,
    color: 'white',
    backgroundColor: '#414849',
    width: '95%'
  },
  email: {
    margin: 15,
    width: '95%'
  },
  username: {
    margin: 15,
    width: '95%'
  },
  password: {
    margin: 15,
    width: '95%'
  },
  confirmPassword : {
    margin: 15,
    width: '95%'
  }
})

表单组件

// need to access error elements, update errors from validator & from server
// and also reset errors either on resubmit, or handleChange
function Form (props){

  function handleChange(event, value){
    const name = event.target.name
    console.log(event.target.value)
  }

  async function onSubmit(props){
   var form = document.querySelector('form')
   var values =  validate.collectFormValues(form)
   console.log(form.email)
   console.log(form.querySelectorAll('p')[0])
    try{
     const results = await props.client
      .mutate({
        mutation: gql`
         mutation register
          ($userName: String!, $email: String!, $password: String!){
            register(userName: $userName, email: $email, password: $password){
              id
              userName
            }
          }`,
        variables: {
          userName: form.userName.value,
          email: form.email.value,
          password: form.password.value,
        }
      })
     console.log(results)
    }
    catch (err) {
      console.log(err)
    }
  }

  const classes = useStyles()
  return(
   <Container component="main" maxWidth="sm">
    <Paper className={classes.paper}>
      <form
        name='form'
        className={classes.form}>
        <TextField
          className={classes.email}
          name='email'
          variant='outlined'
          type='text'
          label='Email'
          InputLabelProps={{
            shrink: true,
          }}
          onChange={(event) => {
            handleChange(event)
          }}/>
        <FormHelperText
          name='emailError'
        >
          Future Email Error
        </FormHelperText>
        <TextField
          className={classes.username}
          name='userName'
          variant='outlined'
          type='text'
          label='Username'
          InputLabelProps={{
            shrink: true,
          }}
          onChange={(event) => {
            handleChange(event)
          }}/>
        <TextField
          className={classes.password}
          name='password'
          variant='outlined'
          type='text'
          label='Password'
          InputLabelProps={{
            shrink: true,
          }}
          onChange={(event) => {
            handleChange(event)
          }}/>
        <TextField
          className={classes.confirmPassword}
          name='confirmPassword'
          variant='outlined'
          type='text'
          label='Confirm Password'
          InputLabelProps={{
           shrink: true,
          }}
          onChange={(event) => {
            handleChange(event)
          }}/>
        <Button
          className={classes.register}
          variant='contained'
          onClick={()=> {
            onSubmit(props)
          }}>
          REGISTER
        </Button>
      </form>
    </Paper>
   </Container>
  )
}

export default Form

标签: node.jsreactjsvalidationgraphqlmaterial-ui

解决方案


我现在把它全部连接起来了,到目前为止一切都很好。我在下面为任何对批评感兴趣的人发布了我的解决方案,或者它可能有助于解决您自己的问题。

在 onSubmit 函数中。

var clientError;
   var form = document.querySelector('form')
   var values =  validate.collectFormValues(form)
   var errors = await validate(values, constraints)

   if(errors == undefined){
     clientError = false
   } else clientError = true

   resetErrors(form)
   handleErrors(form, errors || {})

   if(clientError == false){
     try{
     const results = await props.client
      .mutate({
        mutation: gql`
         mutation register
          ($userName: String!, $email: String!, $password: String!){
            register(userName: $userName, email: $email, password: $password){
              id
              userName
            }
          }`,
        variables: {
          userName: form.userName.value,
          email: form.email.value,
          password: form.password.value,
        }
      })
     console.log(results)
     props.props.history.push('/login')

    }
    catch (err) {
      handleGraphqlErrors(form, err)
    }
   }
  }

错误处理的实际功能

//handle return errors from mutation
  function handleGraphqlErrors(form, err){
    const graphqlErrors = err.toString().slice(22)
    console.log(graphqlErrors)
    if(graphqlErrors == 'Username is already taken'){
      document.getElementById('userNameError').innerHTML = graphqlErrors
    }
    if(graphqlErrors == 'Email is already in use'){
      document.getElementById('emailError').innerHTML = graphqlErrors
    }
  }

  //map errors to proper input fields
  function handleErrors(form, errors){
    Object.keys(errors).map((key, index) => {
      console.log(errors[key])
      document.getElementById(`${key}Error`).innerHTML = errors[key]
    })
  }

  //reset error input fields to blank
  function resetErrors(form){
    var errorInputs = form.querySelectorAll('p')
    Object.keys(errorInputs).map(key => {
      errorInputs[key].innerHTML = ''
    })
  }

推荐阅读