React Hook Form FKJ
by Faisal Khan Janjua
HTML
import React, { useEffect, useState } from 'react';
const SmartForm = ( form_fields, validationSchema, onSubmit, formIdentifier ) => {
const [formData, setFormData] = useState(form_fields); // getting field values and using in state
const [errors, setErrors] = useState({});
useEffect(() => {
if (form_fields !== formData) {
setFormData(form_fields);
}
}, [form_fields]);
const extractErrors = (err) => {
let errors = {};
err && err.inner && err.inner.map(e => errors[e.path] = e.message);
return errors;
};
const onChangeField = (e) => {
const field = e.currentTarget;
const { name, value, type, checked, tagName } = field;
if (tagName === 'SELECT' && field.multiple) formData[name] = [...field.options].filter(o => o.selected).map(o => o.value);
else formData[name] = value;
if(type === 'checkbox') {
formData[name] = checked ? 1 : '';
}
setFormData(prevFormData => ({
...prevFormData,
[name]: formData[name]
}));
if((type === 'checkbox') || (field.hasAttribute('validateoninput') && field.getAttribute('validateoninput').trim().toLowerCase() === 'true')) {
validateField(e);
}
};
const validateField = async ({ currentTarget: field }) => {
const { name } = field;
let all_errors = {};
try {
await validationSchema.validate(formData, { abortEarly: false });
} catch (err) {
all_errors = extractErrors(err); // getting all errors at once
}
// mapping only current error, it is re-using same logic
setErrors((prevErrors) => ({
...prevErrors,
[name]: all_errors[name] || null,
}))
};
const validateAndSubmit = async (e) => {
e.preventDefault();
for (const elm of e.target.elements) {
// check if still selected value is...
React
import React, { useState } from 'react';
import * as Yup from 'yup';
import SmartForm from '../../Components/form';
import { API_URL } from '../../AppConfiguration/config';
import DoHttp from '../../Services/http';
const DemoForm = () => {
const fields = {
any_string: 'Faisal',
email_address: '',
password: '',
confirmPassword: '',
optionalNumber: '',
mustNot0: '',
startDate: '',
endDate: '',
country: '',
regions: '',
is_applicable: '',
extra_info: '',
checkbox: '1',
cars: '',
textarea: '',
iAccept: '',
};
const [form_fields, set_form_fields] = useState(fields);
const [applicable, set_applicable] = useState(false);
const formIdentifier = 'my_demo_form';
const subtractDays = (date, n) => new Date(date.setDate(date.getDate() - n));
const addMonths = (date, n) => new Date(date.setMonth(date.getMonth() + n));
// const addDays = (date, n) => new Date(date.setDate(date.getDate() + n));
const dt_today = subtractDays(new Date(), 1);
const dt_validTill = addMonths(new Date(), 3);
const validation_rules = {
any_string: Yup.string().required('This is required'),
email_address: Yup.string().matches(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/, 'Must be Valid Email address').required('Email is required'),
password: Yup.string().min(8, 'Password must have 8 characters').max(15, 'Password must not exceed 15 characters').required('Password is required'),
confirmPassword: Yup.string().oneOf([Yup.ref('password'), null], 'Passwords do not match'),
optionalNumber: Yup.lazy(value => {
if (value) return Yup.string().matches(/^[0-9]+$/, 'Not a valid number');
else return Yup.string().notRequired();
}),
mustNot0: Yup.number().notOneOf([0], '0 is not allowed').max(99, 'can not exceed 99').typeError('Not a valid...