I have two problems with my Formik form. The first problem is with the group selection. I am calling to my database and getting a response back with proper data but its not showing up in the select field. What confuse me is I am getting the gender to populate no problem although I have it hard coded in the file.
The second problem is the Formik state is not reading the church field. I have it disable because its populate based on the user who is log in jwt token. So there is no mistake when a user tries to create a member and create him/her in the wrong church.
Api Call
const Create2 = () => {
const isNonMobile = useMediaQuery("(min-width:600px)")
const [groups, setGroups] = useState([])
const [churches, setChurches] = useState([]);
const [churchId, setChurchId] = useState(getChurchId());
const handleFormSubmit = (values) =>{
console.log(values);
}
const options = [
{ id: 1, value: 'male', label: 'Male' },
{ id: 2, value: 'female', label: 'Female' },
];
const getChurchNameById = (id) => {
// console.log('Churches:', churches);
// console.log('Target ChurchId:', id);
if (id === null || id === undefined) {
// console.error('Invalid Church ID');
return "";
}
const church = churches.find((church) => church.churchId === parseInt(churchId));
// console.log('Found Church:', church);
return church ? church.churchName : ""; // Return an empty string if not found
};
const initialValues = {
firstName: "",
lastName: "",
gender: "",
group: "",
church: "", // getChurchNameById(churchId) || ""
isActive: ""
}
const memberSchema = yup.object().shape({
firstName: yup.string().required("required"),
lastName: yup.string().required("required"),
gender: yup.string().required("required"),
group: yup.string().required("required"),
church: yup.string().required("required"),
isActive: yup.string().required("required"),
})
useEffect(() => {
console.log("useEffect is running");
const fetchData = async () => {
try {
const groupResponse = await GroupService.allGroups();
const churchResponse = await ChurchService.allChurches();
if (groupResponse.$values && churchResponse.$values) {
// Map groups to the format expected by Select component
const groups = groupResponse.$values.map(group => ({
label: group.groupName,
value: group.groupId.toString(),
}));
// setGroups(groupResponse.$values, ...Groups);
setGroups(groups);
setChurches(churchResponse.$values);
// Log the groups data
// console.log("Groups Data:", Groups);
// Assuming you have a function to get the churchId from JWT token
const tokenChurchId = getChurchId(); // Replace with the actual function
console.log("Token ChurchId:", tokenChurchId);
// Log the updated state after the state has been updated
// console.log("Updated Groups:", groupResponse.$values, ...Groups);
// console.log("Updated Churches:", churchResponse.$values);
// console.log("Updated ChurchId:", tokenChurchId);
// Update the churchId state
setChurchId(tokenChurchId);
} else {
console.error("Unexpected response format or API request failed");
}
// Rest of your code...
} catch (error) {
console.error("Error fetching data:", error);
}
};
fetchData();
}, []);
Formik form
<Formik
onSubmit={handleFormSubmit}
initialValues={initialValues}
validationSchema={memberSchema}
>
{({values,errors, touched, handleBlur, handleChange, handleSubmit})=>(
<form onSubmit={handleSubmit} className="createMember-form">
{console.log("Formik State:", values)}
<Box
display="grid"
gap="30px"
gridTemplateColumns="repeat(4, minmax(0,1fr))"
sx={{
"& > div": {gridColumn: isNonMobile ? undefined : "span 4"}
}}
>
<TextField
fullWidth
variant="filled"
type="text"
label="First Name"
onBlur={handleBlur}
onChange={handleChange}
value={values.firstName}
name="firstName"
error={!!touched.firstName && !!errors.firstName}
helperText={touched.firstName && errors.firstName}
sx={{gridColumn: "span 2"}}
/>
<TextField
fullWidth
variant="filled"
type="text"
label="Last Name"
onBlur={handleBlur}
onChange={handleChange}
value={values.lastName}
name="lastName"
error={!!touched.lastName && !!errors.lastName}
helperText={touched.lastName && errors.lastName}
sx={{gridColumn: "span 2"}}
/>
<TextField fullWidth variant="filled" sx={{gridColumn: "span 2"}}
select
id="gender"
label="Gender"
onBlur={handleBlur}
onChange={handleChange}
value={values.gender ?? ""}
name="gender"
error={!!touched.gender && !!errors.gender}
helperText={touched.gender && errors.gender}
>
{options.map((option)=>(
<MenuItem key={option.id} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
<TextField fullWidth variant="filled" sx={{ gridColumn: "span 2" }}
select
id="group"
label="Group"
onBlur={handleBlur}
onChange={handleChange}
value={values.group ?? ""}
name="group"
error={!!touched.group && !!errors.group}
helperText={touched.group && errors.group}
>
{groups.map((group) => (
<MenuItem key={group.groupId} value={group.groupId}>
{group.groupName}
</MenuItem>
))}
{console.log("Current value of 'group':", values.group)}
</TextField>
<TextField
fullWidth
variant="filled"
type="text"
label="Church"
onBlur={handleBlur}
onChange={handleChange}
value={getChurchNameById(churchId)}
name="church"
disabled
sx={{ gridColumn: "span 4" }}
/>
</Box>
<Box display="flex" justifyContent="end" mt="20px" gap={2}>
<Button type="reset" color="secondary">
Reset
</Button>
<Button type="submit" color="secondary" variant="contained">
Create New Member
</Button>
</Box>
</form>
)}
</Formik>
Okay, I dont exactly know if this is all, but I did catch some stuff. Firstly, on the Api Call you have this:
const groups = groupResponse.$values.map(group => ({
label: group.groupName,
value: group.groupId.toString(),
}));
// setGroups(groupResponse.$values, ...Groups);
setGroups(groups);
But then when you're rendering you are doing this:
{groups.map((group) => (
<MenuItem key={group.groupId} value={group.groupId}>
{group.groupName}
</MenuItem>
))}
So you are setting groups to be an array of objects that have label and value, but then you are using groups.groupId and groups.groupName again, that shouldn't exist after the first code is run.
Secondly, Formiuk does not read disabled fields, this is an intended behaviour. So one solution if you still want it to be on the form submission data is to instead make it hidden somehow, not disabled.