I'm using a custom hook called useMultiStepForm to manage a multi-step form in my React application. The hook provides the current step index (currentStepIndex) among other functionalities. I need to access the currentStepIndex value outside of the useMultiStepForm hook, specifically in the validationSchema configuration of formik. However, when I try to pass currentStepIndex to another function or variable, I encounter a reference error: "Uncaught ReferenceError: can't access lexical declaration 'currentStepIndex' before initialization."
I'm able to use other values from the useMultiStepForm hook, such as isLastStep, without any error. But accessing currentStepIndex seems to be causing the issue.
Is there a way to access the currentStepIndex value outside of the useMultiStepForm hook without encountering the reference error? I'm looking for a solution or workaround that allows me to pass the currentStepIndex value to other parts of my code, specifically to the validationSchema configuration of formik.
Any help or suggestions would be greatly appreciated. Thank you!
here is the code
const NewRecord = () => {
const formik = useFormik({
initialValues: {
houseHolderName: "",
houseHolderNo: "",
email: "",
address: "",
phone: "",
numberOfFamilyMembers: "2",
familyMembersDetails: [],
waterAvialablity: true,
powerAvailability: true,
owenership: true,
},
validationSchema: recordSchema(currentStepIndex), // here I want to pass current step index but I am getting error - Uncaught ReferenceError: can't access lexical declaration 'currentStepIndex' before initialization
onSubmit: (data) => {
if (!isLastStep) return next(); // in here I am not getting any error even though it is also comming from useMultiStepForm hook
// make api call here // data oject contains all of the data
},
});
const handleAddFamilyMember = () => {
formik.setFieldValue(
"familyMembersDetails",
[
...Array(parseInt(formik.values.numberOfFamilyMembers)).fill({
fullName: "",
dateOfBirth: "",
nic: "",
passport: "",
advancedLevel: "",
ordinaryLevel: "",
higherStudies: "",
gender: "",
profession: "",
}),
],
true
);
};
const { currentStepIndex, step, next, previous, isFirstStep, isLastStep } =
useMultiStepForm([
<FamilyDetails
values={{ ...formik.values }}
updateField={formik.handleChange}
errors={{ ...formik.errors }}
/>,
<FamilyMembersDetails
values={{ ...formik.values }}
updateField={formik.handleChange}
errors={{ ...formik.errors }}
handleAddFamilyMember={handleAddFamilyMember}
/>,
<FamilyMemberDiseaseDetails
values={{ ...formik.values }}
updateField={formik.handleChange}
errors={{ ...formik.errors }}
handleAddFamilyMember={handleAddFamilyMember}
/>,
<HomeDetails
values={{ ...formik.values }}
updateField={formik.handleChange}
errors={{ ...formik.errors }}
/>,
<VehicleDetails
values={{ ...formik.values }}
updateField={formik.handleChange}
errors={{ ...formik.errors }}
/>,
<Summary values={{ ...formik.values }} />,
]);
return (
<NewRecordContainer>
<div>
<StepIndicator
labels={["Family", "Members", "Deices", "Home", "Vehicle", "Summary"]}
currentStepIndex={currentStepIndex}
/>
<form action="#" onSubmit={formik.handleSubmit}>
<div style={{ minHeight: 350 }}>{step}</div>
<ControllerButtons>
<button
onClick={previous}
type="button"
className="btn btn-secondary"
style={{ opacity: isFirstStep ? ".6" : "1" }}
>
Back
</button>
<button type="submit" className="btn btn-primary">
{isLastStep ? "Submit" : "Next"}
</button>
</ControllerButtons>
</form>
</div>
</NewRecordContainer>
);
};
export default NewRecord;
this useMultiStepForm hook
import { useState } from "react";
export function useMultiStepForm(steps) {
const [currentStepIndex, setCurrentStepIndex] = useState(0);
function next() {
setCurrentStepIndex((prev) => {
if (prev >= steps.length - 1) return prev;
return prev + 1;
});
}
function previous() {
setCurrentStepIndex((prev) => {
if (prev <= 0) return prev;
return prev - 1;
});
}
function goTo(index) {
setCurrentStepIndex(index);
}
return {
currentStepIndex,
step: steps[currentStepIndex],
next,
previous,
goTo,
steps,
isFirstStep: currentStepIndex === 0,
isLastStep: currentStepIndex === steps.length - 1,
};
}
Edited here is the record schema
import * as Yup from "yup";
export const recordSchema = (step) => {
return Yup.lazy((values) => {
if (step === step) { // I want make familyMembersDetails array required if current step 2
return Yup.object({
...values,
familyMembersDetails: Yup.array()
.of(
Yup.object({
fullName: Yup.string().required("Full Name is required"),
dateOfBirth: Yup.string().required("Date of birth is required"),
nic: Yup.string(),
passport: Yup.string(),
advancedLevel: Yup.string(),
ordinaryLevel: Yup.string(),
higherStudies: Yup.string(),
gender: Yup.string().required("Select Gender"),
profession: Yup.string(),
})
)
.required("Family members details are required"),
});
} else {
return Yup.object({
houseHolderName: Yup.string()
.max(25, "Must be 25 characters or less")
.required("House Holder Name is required"),
email: Yup.string()
.email("Invalid email address")
.required("Email is required"),
address: Yup.string().required("Address is required"),
phone: Yup.string().required("Phone number is required"),
houseHolderNo: Yup.string().required(
"House Holder Number is required."
),
numberOfFamilyMembers: Yup.string().required(
"Number of family member is required"
),
});
}
});
};