Search code examples
reactjstextfieldformik

My Formik form is not populating data from database


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>




Solution

  • 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.