I am trying to use formik and yup valiation first time, I have created a Select Field and have put some options , after selecting the option everytime it keep showing the validation error message ,
can anyone help me to fix it
the codesandbox link for error
const InvestmentDetail = ({ data, changeValue }) => {
return (
<div className="text-2xl flex flex-col w-full justify-between container w-[1128px] gap-[42px] pt-[35px] pb-[50px] ">
{investmentDetails.map((i, _i) => {
return (
<>
<div>
<div className="text-[22px]"> {i.label} </div>
<div className="text-lg text-[#404040]"> {i.desc}</div>
</div>
<div className="flex flex-col w-full">
<Field
as="select"
name={i.label}
id="dropdown"
className="appearance-none relative !w-full p-[16px] h-[4.06rem] border-[#787878] rounded-[6px] border-solid border-[1px] bg-[#fff]"
value={data[i.label]}
onChange={(e) => changeValue(i.label, e.target.value)}
>
<option value="" className="text-2xl">
Select
</option>
{i.options.map((i) => (
<>
<option key={i} value={i} className="text-2xl">
{i}
</option>
<br />
</>
))}
</Field>
<ErrorMessage
name={i.label}
component="div"
className="error bottom-[-10px] text-[red] text-xl"
/>
</div>
</>
);
})}
</div>
);
};
export default function App() {
const [formData, setFormData] = useState(initialStates);
useEffect(() => {}, [formData, setFormData]);
const changeValue = (key, value) => {
setFormData((prevData) => ({
...prevData,
[key]: value
}));
};
return (
<>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={() => console.log("high")}
>
<Form>
<InvestmentDetail data={formData} changeValue={changeValue} />
</Form>
</Formik>{" "}
</>
);
}
validation schema and initial states :
import * as Yup from "yup";
export const investmentDetails = [
{
label: "Account Type",
desc: "",
options: ["Saving", "Current"]
},
{
label: "Portfolio/Strategy Name",
desc: "",
options: ["Saving", "Current"]
},
{
label: "Fund Fees Category",
desc: "Fees preview according to selection",
options: ["Saving", "Current"]
},
{
label: "Investment Category",
desc: "Preview only when systematic transfer plan is selected",
options: ["Saving", "Current"]
},
{
label: "Country of Tax Residency",
desc: "Preview only when systematic transfer plan is selected",
options: ["Saving", "Current"]
},
{
label: "No. of Account Holders",
desc: "Preview only when systematic transfer plan is selected",
options: ["Saving", "Current"]
},
{
label: "Investment Mode",
desc: "Preview only when systematic transfer plan is selected",
options: ["Saving", "Current"]
}
];
export const initialValues = {
"Account Type": "",
"Portfolio/Strategy Name": "",
"Fund Fees Category": "",
"Investment Category": "",
"Communication Address": "",
"Country of Tax Residency": "",
"No. of Account Holders": "",
"Quantum of Investment": "",
"Investment Mode": ""
};
export const initialStates = {
"Account Type": "",
"Portfolio/Strategy Name": "",
"Fund Fees Category": "",
"Investment Category": "",
"Communication Address": "",
"Country of Tax Residency": "",
"No. of Account Holders": 1,
"Quantum of Investment": "",
"Investment Mode": ""
};
export const validationSchema = Yup.object().shape({
"Account Type": Yup.string().required("Required"),
"Portfolio/Strategy Name": Yup.string().required("Required"),
"Fund Fees Category": Yup.string().required("Required"),
"Investment Category": Yup.string().required("Required"),
"Country of Tax Residency": Yup.string().required("Required"),
"No. of Account Holders": Yup.number()
.required("Required")
.min(1, "Should be at least 1"),
"Investment Mode": Yup.string().required("Required")
});
You should use formik
features to access or change values in app and prevent set field value on onChange
property of Field
component because <Field/>
automatically set value as the document has mentioned.
<Field />
will automagically hook up inputs to Formik. It uses the name attribute to match up with Formik state. will default to an HTML element.
<Field
as="select"
name={i.label}
id="dropdown"
className="appearance-none relative !w-full p-[16px] h-[4.06rem] border-[#787878] rounded-[6px] border-solid border-[1px] bg-[#fff]"
value={data[i.label]}
>
<option value="" className="text-2xl">
Select
</option>
{i.options.map((i) => (
<>
<option key={i} value={i} className="text-2xl">
{i}
</option>
<br />
</>
))}
</Field>
Actually formData
setState in App component is redundant and you will access to values on onSubmit callback as follows:
<Formik
validateOnChange={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
>
<Form>
<InvestmentDetail data={formData} changeValue={changeValue} />
</Form>
</Formik>