使用 Laravel Passport 时,在 React JS 中努力显示验证错误

Struggling to display validation errors in React JS when using Laravel Passport

我正在构建我的第一个 React JS 系统并使用 Laravel Passport 进行身份验证。在我尝试提交无效数据之前,它一直运行良好。当我发送 post 请求时,我设置了以下请求 class:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class RegisterUser extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|confirmed|min:8'
        ];
    }
}

从以下 React JS 方法中看到的 /api/register 端点触发:

registrationHandler = e => {
        e.preventDefault();

        $("#email-login-btn")
            .attr("disabled", "disabled")
            .html(
                '<i class="fas fa-spinner fa-spin fa-1x fa-fw"></i><span class="sr-only">Loading...</span>'
            );

        var formData = new FormData();
        formData.append("email", e.target.elements.email.value);
        formData.append("name", e.target.elements.name.value);
        formData.append("password", e.target.elements.password.value);
        formData.append(
            "password_confirmation",
            e.target.elements.password_confirmation.value
        );

        axios
            .post("/api/register", formData)
            .then(response => {
                return response;
            })
            .then(json => {
                if (json.status == 201) {
                    const MySwal = withReactContent(
                        Swal.mixin({
                            toast: true,
                            position: "top-end",
                            showConfirmButton: false,
                            timer: 3000
                        })
                    );

                    MySwal.fire({
                        type: "success",
                        title: "Registered successfully"
                    });
                } else {
                    $("#email-login-btn")
                        .removeAttr("disabled")
                        .html("Register");
                }
            })
            .catch(error => {
                console.log(error.response.data.errors);
                $("#email-login-btn")
                    .removeAttr("disabled")
                    .html("Register");
            });
    };

你可以在底部看到我正在尝试捕获错误并使用 console.log(error.response.data.errors); 将它们记录到控制台 - 这很好用,我可以在控制台中看到它们,如下所示:

我的控制器方法是这样的,没有什么疯狂的:

    {
        // If validation hasn't failed, register the user
        User::create([
            'name' => request('name'),
            'email' => request('email'),
            'password' => bcrypt(request('password'))
        ]);

        return response()->json(['status' => 201]);
    }

但我现在要做的是在我的表格下方的注册页面上显示错误。我已经尝试在状态中设置错误(我正在执行控制台日志),然后将它们作为道具传递给我的 Register.js 文件,但它总是 returns "undefined",大概因为路线没有改变。

有没有更好的方法来显示系统返回的错误?我目前对此有点不知所措。

谢谢!

所以我通过做几件事实现了这一目标:

首先,我创建了一个新的子组件来处理错误的显示,Error.js

import React from "react";

class Error extends React.Component {
    render() {
        return (
            <>
                <li className="text-danger">{this.props.message}</li>
            </>
        );
    }
}

export default Error;

然后我将其导入到 Register.js 文件的顶部。

import Error from "./Error";

然后在 render() 函数中 Register.js 我添加了这个块:

<ul>
    {Object.keys(errors).map((error, index) => (
        <Error
            message={errors[error][0]}
            key={shortid.generate()}
        />
    ))}
</ul>

你会注意到我使用 shortid.generate() 作为我的密钥,这是因为我从 Laravel 收到的数据实际上并不包含任何我可以用作唯一密钥的东西每个物品。 This package 似乎对我来说效果很好。

我最初使用 .map 遍历错误数组的想法之所以失败,是因为 Laravel 实际上向我发送了一个对象,而不是一个数组。因此,将这个想法转换为在对象上循环的东西非常有效 - Object.keys(errors).map((error, index)

我知道这个问题得到了回答,但我给出这个答案是为了帮助那些想要处理“错误的粒度分布”的人,通过粒度的方式,比如 Laravel 给你一个“错误”的对象“作为回应,这样您就可以在出现错误时将每个错误显示在输入字段附近,以便更好地呈现,我会分享图像。我使用的是 react-bootstrap 但在每种情况下概念都是相似的。 注意:整个答案是concept-oriented,请注意概念。我详细解释了一切。


您可以简单地从“错误对象”中获取每个错误。

    import React, { useState } from "react";
      import axios from "axios";


    function Registration(){
      const [userRegistrationData, setUserRegistrationData] = useState({ username:''});

      const [userRegErrors, setUserRegErrors] = useState({usernameError:''});

    const onInputchange = (e) => {

    setUserRegistrationData({...userRegistrationData, [e.target.name]: e.target.value });
      };

    
    const registerUser=(e)=>{
      e.preventDefault();

   

     let username = userRegistrationData.username
        
        //you can use Axios here, that Axios function will return the validation response or errors response from your Laravel API
        
      //note the errors would be caught in the catch block of your code, you can check your data by console log and then do your work accordingly. you can take an example from below

          axios.get('/user?ID=12345')
       .then(function (response) {
    // handle success
    console.log(response);
  })
       .catch(function (error) {
    // handle error
    console.log(error.response);
      setUserRegErrors({usernameError:error.response.errors.username});
  })
      .then(function () {
    // always executed
  });
     }
          
    }
    
    
    let usernameError;
    
    //userRegistrationErrors.error is the variable which has store the object of errors it is for concept purposes, you can use axios to fetch the data
    if(userRegErrors.error){
    usernameError=userRegErrors.error.username;
       }
    
     
      return (  <> 
        <form onSubmit={registerUser} >
        <FloatingLabel  label="Username">
                          <Form.Control
                            type="input"
                            placeholder=" "
                            name="username"
                            value={userRegistrationData.username}
        
                            required
                            onChange={(e)=>onInputchange(e)}
                            isInvalid={usernameError?true:false}
        
                          />
                        </FloatingLabel>
                        {usernameError?<div className="validation-error">The username already exists in our system !</div>:''}
        
        </form>
    </>
    )
        }
    
    export default Registration