Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do I do server side validation using Formik and Yup?

I'm trying to validate a email field on a sign up form to check if it already exist. To do this I'm checking the running a GET request on the server that returns true and false.

This is my validation Schema for the field:

validationSchema={
    yup.object().shape({
        registrationEmail: yup.string().email('Invalid email').test('Unique Email','Email already in use', async (value) => {axios.get('http://localhost:5000/users/register', value).catch(err => console.log(err)) })
    })
}

The problem seems to be that the values field is blank. How do I past the value from the Formik Field to my function?

EDIT: Managed to send value using the following

registrationEmail: yup.string().email('Invalid email').test('Unique Email','Email already in use', function(value){return new Promise((resolve, reject) => {axios.get('http://localhost:5000/users/register', value)})})

I'm still having troubles returning a response this is what the route looks like

router.get('/register', (req, res) => {
    User.findOne({email: req.body.email}).then(user => {
        if(user){
            return true
        }else{
            return false
        }
    })
})
like image 970
itsOnly1_Jah Avatar asked Mar 24 '20 20:03

itsOnly1_Jah


People also ask

How do I validate server side form?

After making an HTML form, you will need to check form validation, because there is no guarantee that the input given by the user is always correct. PHP can validate form input server side, submitted by the user using HTML forms. You need to check a few things: Numbers only.

How do you validate Formik field?

Formik supports field-level validation via the validate prop of <Field> / <FastField> components or useField hook. This function can be synchronous or asynchronous (return a Promise). It will run after any onChange and onBlur by default.

How do I validate a form in formik?

Manually Triggering Validation You can manually trigger both form-level and field-level validation with Formik using the validateForm and validateField methods respectively. 1 import React from 'react'; 2 import { Formik, Form, Field } from 'formik';

What is formik and Yup?

Here comes Formik and Yup to the rescue! Formik is designed to manage forms with complex validation with ease. Formik supports synchronous and asynchronous form-level and field-level validation. Furthermore, it comes with baked-in support for schema-based form-level validation through Yup.

How do I create a Yup validation schema in useformik?

Yup validation schemas are created using Yup.object method which takes as a parameter an object. This object has the field names as properties and their values are validation rules from the Yup library. Then, add the property validationSchema to the object passed to useFormik with the following value:

Which fields are not validated during form validation/submission?

Note: The <Field>/<FastField> components' validate function will only be executed on mounted fields. That is to say, if any of your fields unmount during the flow of your form (e.g. Material-UI's <Tabs> unmounts the previous <Tab> your user was on), those fields will not be validated during form validation/submission.


2 Answers

I solved my problem for the validation I did the following:

 registrationEmail: yup.string().email('Invalid email')
                        .test('Unique Email','Email already in use', 
                            function(value){return new Promise((resolve, reject) => {
                                axios.post('http://localhost:5000/users/register/validEmail', {'email': value})
                                .then(res => {if(res.data.msg === 'Username already been taken'){resolve(false)} resolve(true)})
                            })}
                        )

For the route:

router.post('/register/validEmail', (req, res) => {
    console.log('Request: ', req.body)
    User.findOne({email: req.body.email}).then(user => {
        if(user){
            console.log({ msg:"Username already been taken" })
            return res.json({ msg:"Username already been taken" })
        }

        console.log({ msg: "Username available." })
        return res.json({ msg: "Username available." })

    }).catch((err)=>{
        console.error(err);
        res.status(400).json('Error: ' + err)
    })
})

Turns out I had to use a POST request or the body of the request would be empty.

like image 188
itsOnly1_Jah Avatar answered Sep 23 '22 07:09

itsOnly1_Jah


I noticed that you had used async/await in your question, but your answer used promises. I prefer async/await and initially thought that it wasn't supported by Yup for their test function because if your solution, but Yup does support async/await! Here's an example of my code for anyone that wants an example. There are also a few examples in the docs: https://github.com/jquense/yup#mixedtestname-string-message-string--function-test-function-schema

username: Yup.string()
      .min(2, 'Too short, minimum 2 characters')
      .max(50, 'Too long, maximum 50 characters')
      .required('Required')
      .test(
        'username-backend-validation',  // Name
        'Username taken',               // Msg
        async (username) => {
          // Res from backend will be flag at res.data.success, true for 
          // username good, false otherwise
          const { data: { success } } = await axios.post(
            "http://localhost:3001/api/users/register/validate-username", 
            { username: username }
          );

          return success
        }
      )
like image 39
Monty Avatar answered Sep 22 '22 07:09

Monty