How to do multiple validations for a single value in yup? - reactjs

Using joi on the server side, I can do multiple validations like
id: [joi.string().email(), joi.string().min(10)].
How can we do this on frontend using formik and yup? I went through the docs and still no success.

You should try Yup like this.
const formikEnhancer = withFormik({
validationSchema: Yup.object().shape({
name: Yup.string().strict(true).lowercase('Name must be lowercase').matches(/^\S+$/, 'Name must not contain spaces').matches(/^(?:(?!\.).)*$\r?\n?/, 'Name must not contain period').max(10, 'Maximum of 10 characters')
.required('Name is required!'),
email: Yup.string().strict(true).lowercase('Email must be lowercase').required('Email is required!')
})
})

Related

Email validation with zod

I have an email input and i want to validate that the user entered a specific email "abcd#fg.com" and if not to show specific error message "This email is not in our database". I am using zod validation to do that, but how can it be done?
const LoginSchema = z.object({
email: z
.string()
.min(1, { message: "This field has to be filled." })
.email("This is not a valid email.")
})
});
I can show how to do this, but I don't think this should be done (more later).
You can use refine to check if the string is exactly some expected value. For example:
const LoginSchema = z.object({
email: z
.string()
.min(1, { message: "This field has to be filled." })
.email("This is not a valid email.")
.refine((e) => e === "abcd#fg.com", "This email is not in our database")
});
Then, later if you were going to pull down emails so you can write a validation on the frontend you would use an async refinement with parseAsync like:
const login2 = z.object({
email: z
.string()
.min(1, { message: "This field has to be filled." })
.email("This is not a valid email.")
.refine(async (e) => {
const emails = await fetchEmails();
return emails.includes(e);
}, "This email is not in our database")
});
Opinion Warning
I would not recommend doing this for 2 reasons:
The number of emails is likely to be very large if you have any meaningful number of users. Pulling all of those down just to make this check would be a pretty big waste of resources and time.
Security wise, sharing emails of all your users publicly over the API strikes me as a dangerous thing to do. Anyone would hit that API to get real email addresses for all of your users.
I would recommend not validating this as part of the data validation. This validation should happen on the backend and return a 4XX error response when logging in.
Edit
A comment on this post mentioned that you could instead provide an API to validate an email address. This could be safely used from an async refinement and avoids the issues described above.
That would look like:
const login2 = z.object({
email: z
.string()
.min(1, { message: "This field has to be filled." })
.email("This is not a valid email.")
.refine(async (e) => {
// Where checkIfEmailIsValid makes a request to the backend
// to see if the email is valid.
return await checkIfEmailIsValid(e);
}, "This email is not in our database")
});

Confirm password validation is not working in react hook form + joi

Confirm password validation is not working here and also error is not showing until I submit it.
const schema = joi
.object({
fullName: joi.string().min(5).max(255).required(),
username: joi.string().min(5).max(255).required(),
email: joi
.string()
.email({ tlds: { allow: false } })
.pattern(new RegExp(patternForEmail))
.message('Invalid email address')
.required(),
password: joi
.string()
.pattern(new RegExp(patternForPassword))
.message(
'Password must contain at least one lowercase letter, one uppercase letter, one number and one special character and minimal length of 8 characters'
)
.required(),
confirmPassword: joi.string().required().valid(joi.ref('password')),
})
.with('password', 'confirmPassword');
check the full code here

react-hooks query and setState causes 500 error

I think this could be a bug or a misconfiguration.
I get this error:
networkError: ServerError: Response not successful: Received status code 500
Submitting the form the first time I would get the desired result, but if I hit the submit button again, I get the networkError message above.
const client = useApolloClient();
const [val, setValu] = useState({
email: 'example#example.com',
password: 'password',
texterror: {
status: false,
text: ''
},
})
//the submit function below:
const handleLogin = async (e) => {
e.preventDefault();
await client.query({
query: Handle_Login,
variables: {
email: val.email,
password: val.password
}
}).then((e) => {
console.log(e)
}).catch((e) => {
setValu({
texterror: {
status: true,
text: 'it be broke yo'
}
})
})
}
However, if I remove setValu({texterror: {status: true, text: 'it be broke yo'}}) in the catch, The 500 error goes away. I could spam the submit button and I wouldn't receive the 500 error.
For right now I'm going to not have a setState inside just to avoid this problem, but I would like to know if there is a solution to this issue.
Any help would be appreciated. Thank you in advance!
At the top level, it's clear that you're causing some kind of error on the server side. A 500 code means there is an "internal server error". So you should really look at your server code and figure out how to safeguard against unexpected input so that it won't error and/or crash but instead return code 400 which is "bad request".
So the question becomes, what about your frontend code is causing a malformed server request?
I suspect that you're trying to use setValu() (which is a React hook) the same way one might use a traditional setState call in a class component. However, they behave quite differently.
In a class component, setState performs a "shallow merge" of the old state and the new state. So if you did:
setState({
texterror: {
status: true,
text: 'it be broke yo'
}
});
If would find only the field texterror on the state object and update that.
However, React hooks work differently. useState() creates a single atomic value, and when you call setValu() it complete replaces the previous value stored in val.
So:
const [val, setValu] = useState({
email: 'example#example.com',
password: 'password',
texterror: {
status: false,
text: ''
},
});
// val is now an object with 'email', 'password', and 'texterror' fields
setValu({
texterror: {
status: true,
text: 'it be broke yo'
}
});
// val is now an object with only a 'texterror' field
In your code when you are using setValu you are wholly replacing the value of val to something that doesn't have an email or password field, which when sent to the server causes an internal server error. A simple fix would be to simply merge the old value of val with the desired new object when you update it:
setValu({
...val,
texterror: {
status: true,
text: 'it be broke yo'
}
});
Remember that with the useState hook you are overwriting the entire state val. This means that you have no longer got a email and password. It is a common oversight when moving from class based components to hooks. Add the parts of the state that didn't change too, and it should all work again.

yupError.inner is undefined while integrating schema with Formik

I tried integrating the Yup's Schema validation with formik. But receiving error as yupError.inner is undefined
Here's a link to codesandbox!
I have'nt tried much. But found this bug report. which was later realized to be resolved. But still i'm recieving the same. Link to issue #1486!.
// VALIDATION SCHEMA
const formSchema = Yup.object().shape({
emailId: Yup.string("Enter a valid string")
.email("Please enter a valid Email ID")
.required("Need your Email ID, we won't spam you!"),
confirmMail: Yup.string("Enter a valid string")
.matches(Yup.ref("emailId"), "Email ID's are not matching")
.required("Please enter a valid mailid"),
mobileNo: Yup.number("Please enter number")
.max(10, "You've entered more than 10 numbers")
.min(10, "You've entered less than 10 numbers")
.required("Password is required"),
password: Yup.string("Enter a valid password").required(
"Password field is required"
),
confirmPassword: Yup.string("Enter a valid password").required(
"Password fields are not matching"
)
});
//Integration of Validation
<Formik
validate
initialValues={this.initialValues}
validationSchema={this.formSchema}
onSubmit={this.handleSubmit}
>
{props => this.renderForm(props)}
</Formik>
Recieving the error yupError.inner is undefined
Bumpup yup to latest and use mixed().test() instead of string().test()
example :
passwordConfirm: Yup.mixed().test('is-same', 'Passwords not match.', value => value === values.newPassword)
The issue is the custom validation for matching the e-mail fields. I made a fork here which I fixed using the method from this Github issue to add a custom validation method to Yup for comparing equality of fields, a feature which is apparently not well-supported.

How to add contact from a rails app to salesforce using restforce gem?

I am using restforce gem to connect to salesforce api. I have successfully connected to it and initialised the client using username/password like below
client = Restforce.new :username => 'foo',
:password => 'bar',
:security_token => 'security token',
:client_id => 'client_id',
:client_secret => 'client_secret'
I am able to create Account in saleforce using the command that is given in gem docs
client.create('Account', Name: 'Foobar Inc.')
Now i want to know how to create contacts? I tried
client.create('Contact', Email: 'demo#example.com')
but it returns false.
I tried
client.create!('Contact', Email: 'demo#example.com')
which showed me the error that LastName is a required field as specified in the comment.
So the solution is to specify LastName also like shown below:
client.create('Contact', Email: 'demo#example.com', LastName: 'Bar')
Thanks and Happy Coding.

Resources