VueJS gère les erreurs dans les appels d'API sur les composants de formulaire
P粉964682904
P粉964682904 2023-09-06 22:01:08
0
2
576

J'ai un point de terminaison d'enregistrement simple que je souhaite permettre aux utilisateurs de s'inscrire dans mon application vue, je souhaite également afficher les erreurs appropriées au client vue depuis mon backend.

La structure JSON de l'erreur ressemble à ceci :

{
    "errors": {
        "Password": [
            "Password is required",
            "Minimum length of 8 characters is required"
        ],
        "UserName": [
            "Username is required",
            "Minimum length of 6 characters is required"
        ],
        "EmailAddress": [
            "Email Address is required",
            "Invalid Email Address"
        ],
        "ConfirmPassword": [
            "Confirm Password is required"
        ]
    }
}

J'ai un composable avec une fonction de registre comme celle-ci :

export default function useAuth() {

    let errors = ref({}) 

    const register = (request) => {

        errors = {}
        AuthService.register(request)
            .then(res => {
                console.log("res: "+ res)
            })
            .catch(err => {
                const errList = err.response.data.errors;
                errors = errList
                // Here i'm getting a reponse
                console.log(errors)

            })
    }
    return {
        register, errors
    }
}

J'ai également un composant de formulaire qui n'est qu'un simple formulaire avec des modèles en V ajoutés :

<script>
// Imports..
export default {
  components: {},
  setup() {

    const { register, errors} = useAuth();

    const request = {
      userName: "",
      emailAddress: "",
      password: "",
      confirmPassword: "",
    };


    const handleSubmit = () => {
        register(request);
        // empty object
        console.log(errors)
      
    };

    return {
      errors,
      request,
      handleSubmit
      
    };
  },
};
</script>

Dans mon composable, je peux déconnecter la réponse d'erreur comme ceci

Réponse d'erreur

J'ai essayé de désenregistrer l'erreur dans le composant formulaire mais maintenant j'obtiens juste un objet vide (j'utilise réactif pour gérer cet objet d'erreur dans le composable)

Réponse d'objet vide à partir d'éléments composables

P粉964682904
P粉964682904

répondre à tous(2)
P粉576184933

On dirait que vous renvoyez un tableau, pas un objet.

Donc, pour y accéder, vous devez faire errors[0].Password.

Allez-vous utiliser un objet ou un tableau (cela peut être utile si vous avez plusieurs erreurs) ?

Si le tableau est attendu et que vous devez vérifier l'attribut Password pour toutes les erreurs, vous feriez quelque chose comme ceci :

errors.find(err => !!err.Password).Password
P粉180844619

Réfléchissez à votre code

Il contient plusieurs erreurs, ce qui rend difficile pour moi de fournir une réponse concise qui corresponde à vos besoins. Au lieu de cela, j'ai rapidement créé un extrait de code qui fonctionne selon vos principes. À l’avenir, j’essaierai de mettre en évidence les points à surveiller et de fournir de bons conseils pour l’avenir.

- Réponse en utilisant async function()可以等待Promise

Pas bon (actuellement console.log 证明使用async si vous souhaitez utiliser les résultats immédiatement)
// YOUR CODE
const handleSubmit = () => {
  register(request); // call PROMISE () 
  // empty object
  console.log(errors)
};

Cela ne fournit pas de résultats immédiats ; l'exécution sur un thread séparé prend un certain temps. En conséquence, le script JavaScript avance presque immédiatement. Normalement, cela entraînera une erreur si vous souhaitez utiliser le résultat immédiatement car la réponse n'est pas encore arrivée.

Donc, lorsque vous essayez d'accéder à errors 的新结果时,您会看到它是空的,即使在 console.log 之后,1-2 秒后,它不会再为空,因为 register(), cela a déjà été exécuté.

D'accord
// SUCCESSFULLY USING
const handleSubmit = async () => {
  await register(request); // call PROMISE () AND WAIT response by await
  // empty object
  console.log(errors)
};

等待 - Attendez la fin du processus - Documentation MDN
异步函数 - 需要什么await Utilisation de - Documentation MDN

- Comment utiliser ref() avec VueJS ?

1.

Stockez les valeurs enregistrées par ref()reactive()compulated(), reactive(), compulated(), etc. dans des variables non modifiables. Utilisez toujours const lors de la déclaration de ces variables.

Plus d'informations - Réponses StackOverflow

Pas bien
// YOUR CODE
let errors = ref({})
D'accord
const errors = ref({})
2.

Vous utilisez le suffixe .value dans une instance et pas dans une autre. Eh bien, ce qui se passe, c'est que le résultat d'une variable .value 后缀,而在另一实例中则不使用。嗯,情况是 ref() 变量的结果始终存储在 .value est toujours stocké dans .value. Vous pouvez le manipuler en conséquence.

Pas bien
// YOUR CODE
let errors = ref({})

// and...
errors = {...}
D'accord
const errors = ref({})

// and...
errors.value = {...}

Comment utiliser ref() ? - Documentation VueJS



Exemple de code avec logique décrite

J'ai commenté ces lignes pour mieux comprendre le code. J'espère que cela est compréhensible.

/**
 ** Need more function for example
 ** !!! The vue is below !!!
 */

// CDN Vue Import
const { createApp, ref, computed } = Vue

// isValideEmail() (JUST EXAMPLE FOR SNIPPET)
// Helper function to validate email address
function isValidEmail(email) {
  const emailRegex = /^\S+@\S+\.\S+$/;
  return emailRegex.test(email);
}

// AuthService (JUST EXAMPLE FOR SNIPPET)
class AuthServiceClass {
  errors
  
  constructor() {
    this.errors = {};
  }

  register(inputs) {
    // Reset Errors
    this.errors = {};
    
    console.log(inputs)
    
    // Check the UserName field
    if (!inputs.userName) {
      this.errors.UserName = (this.errors?.UserName ?? []).concat("Username is required");
    }
    if (!inputs.userName || inputs.userName.length < 6) {
      this.errors.UserName = (this.errors?.UserName ?? []).concat("Minimum length of 6 characters is required");
    }

    // Check the EmailAddress field
    if (!inputs.emailAddress) {
      this.errors.EmailAddress = (this.errors?.EmailAddress ?? []).concat("Email Address is required");
    }
    if (!inputs.emailAddress || !isValidEmail(inputs.emailAddress)) {
      this.errors.EmailAddress = (this.errors?.EmailAddress ?? []).concat("Invalid Email Address");
    }

    // Check the Password field
    if (!inputs.password) {
      this.errors.Password = (this.errors?.Password ?? []).concat("Password is required");
    }
    if (!inputs.password || inputs.password.length < 8) {
      this.errors.Password = (this.errors?.Password ?? []).concat("Minimum length of 8 characters is required");
    }

    // Check the ConfirmPassword field
    if (!inputs.confirmPassword) {
      this.errors.ConfirmPassword = (this.errors?.ConfirmPassword ?? []).concat("Confirm Password is required");
    }
    
    // Return with Promise because its just a simulate your really AuthService.register
    return new Promise((resolve, reject) => {
      if (this.errors.length !== 0) {
        reject({ errors: this.errors });
      } else {
        resolve({ success: true, errors: null });
      }
    });
  }
}
// Import AuthService (JUST EXAMPLE FOR SNIPPET)
const AuthService = new AuthServiceClass()

// Declare useAuth() (JUST EXAMPLE FOR SNIPPET)
function useAuth()
{
    const errors = ref({}) 

    const register = async (request) => {
        await AuthService.register(request)
          .then(res => {
            console.log("AuthService Register Successfully Response", res)
          })
          .catch(err => {
            console.log("AuthService Register Error Response", err)
            const newErrors = err.errors;
            errors.value = newErrors
          })
    }
    
    return { register, errors }
}

/**
 ** !!!!!!
 ** Here's started vue code snippet
 */

// Component.vue
const app = createApp({
  setup() {
    // Get register() and errors Ref
    const { register, errors } = useAuth();

    // Declare Ref Object for inputs
    const request = ref({
      userName: "",
      emailAddress: "",
      password: "",
      confirmPassword: "",
    });

    // Declare Submit Function (async for Promise check !!!)
    const handleSubmit = async () => {
        console.log('') // just log
        console.log('Detect New Handle') // just log

        // call register() function with our value of inputs
        // wait answer by "await"
        await register(request.value);

        console.log('HandleSubmit - Check Error List', errors.value) // just log
    };
    
    // Just Extra Computed Value, not important
    // return true/false
    const hasError = computed(() => Object.keys(errors.value).length > 0)
    
    return { hasError, errors, request, handleSubmit }
  },
}).mount('#app')
.input {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 10px;
  max-width: 200px;
}

.error {
  color: red;
}
<!-- Component.vue -->

<script src="https://unpkg.com/vue@3.3.4/dist/vue.global.prod.js"></script>

<div id="app">
  <div>
    <!-- Display Errors -->
    <div v-if="hasError">
      <!-- errors is an object, so you can foreach its keys -->
      <div v-for="inputName of Object.keys(errors)">
        <span>{{ inputName }}:</span>
        <!-- name-array pairs can be directly printed as error messages -->
        <div v-for="errorMessage of errors[inputName]" class="error">
          {{ errorMessage }}
        </div>
      </div>
    </div>
    <!-- Inputs -->
    <!-- request is an object, so you can foreach its keys -->
    <div class="input" v-for="inputName of Object.keys(request)">
      <label>{{ inputName }}</label>
      <input v-model="request[inputName]" />
    </div>
    <!-- Submit Button -->
    <button @click="handleSubmit">Submit</button>
  </div>
</div>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal