I am getting undefined states in my UI in React component

41 Views Asked by At

I have divided my code into three different files for modularity.

  • ProfessionalInfo.js -> that binds logic with UI.
  • professionalInfoUI -> the Form UI
  • useProfessionalInfoForm -> all of my logic goes here.

useProfessionalInfoForm:

    // useProfessionalInfoForm.js
    import { useEffect } from "react";
    import { toast } from "react-toastify";
    import { professionalInfoAPI } from "../../../../api/professionalInfo";
    import useProfessionalInfoStore from "../../../../zustand/ProfessionalInfoStore";
    
    const useProfessionalInfoForm = () => {
      const professionalInfo = useProfessionalInfoStore(
        (state) => state.professionalInfo
      );
      const setProfessionalInfo = useProfessionalInfoStore(
        (state) => state.setProfessionalInfo
      );
      const resetProfessionalInfo = useProfessionalInfoStore(
        (state) => state.resetProfessionalInfo
      );
    
      useEffect(() => {
        if (!professionalInfo.workExperiences) {
          setProfessionalInfo((state) => ({
            ...state,
            workExperiences: [],
          }));
        }
      }, []);
    
      const handleChange = (e) => {
        const { name, value } = e.target;
        setProfessionalInfo((state) => ({
          ...state,
          [name]: value,
        }));
      };
    
      const handleWorkChange = (e, index) => {
        const { name, value } = e.target;
        setProfessionalInfo((state) => ({
          ...state,
          workExperiences: state.workExperiences.map((exp, i) =>
            i === index ? { ...exp, [name]: value } : exp
          ),
        }));
      };
    
      const handleAddWorkExperience = () => {
        setProfessionalInfo((state) => ({
          ...state,
          workExperiences: [
            ...state.workExperiences,
            { start: null, end: null, work: "" },
          ],
        }));
      };
    
      const handleRemoveWorkExperience = (index) => {
        setProfessionalInfo((state) => ({
          ...state,
          workExperiences: state.workExperiences.filter((_, i) => i !== index),
        }));
      };
    
      const handleWorkDateChange = (date, index, fieldName) => {
        setProfessionalInfo((state) => ({
          ...state,
          workExperiences: state.workExperiences.map((exp, i) =>
            i === index ? { ...exp, [fieldName]: date } : exp
          ),
        }));
      };
    
      const handleSubmit = () => {
        professionalInfoAPI(professionalInfo)
          .then((response) => {
            toast.success("Data has been sent!", {
              position: toast.POSITION.TOP_RIGHT,
              autoClose: 2000,
              closeOnClick: true,
              pauseOnHover: true,
              draggable: true,
            });
            // Optionally, you can reset the form after successful submission
            resetProfessionalInfo();
          })
          .catch((error) => {
            toast.error(
              "An error occurred while sending data. Please try again later.",
              {
                position: toast.POSITION.TOP_RIGHT,
                autoClose: 2000,
                closeOnClick: true,
                pauseOnHover: true,
                draggable: true,
              }
            );
            console.error("Error:", error);
          });
      };
    
      const handleReset = () => {
        resetProfessionalInfo();
      };
    
      return {
        professionalInfo,
        handleChange,
        handleWorkChange,
        handleAddWorkExperience,
        handleRemoveWorkExperience,
        handleWorkDateChange,
        handleSubmit,
        handleReset,
      };
    };
    
    export default useProfessionalInfoForm;

professionalInfoUI:

    import React from "react";
    import Grid from "@mui/material/Grid";
    import Typography from "@mui/material/Typography";
    import TextField from "@mui/material/TextField";
    import { Button } from "@mui/material";
    import DatePicker from "react-datepicker";
    import "react-datepicker/dist/react-datepicker.css";
    
    const ProfessionalInfoUI = ({
      professionalInfo,
      handleChange,
      handleWorkChange,
      handleWorkDateChange,
      handleAddWorkExperience,
      handleRemoveWorkExperience,
      handleSubmit,
      handleReset,
    }) => {
        console.log('professionalInfoUi: ', professionalInfo)
      return (
        <>
          <Typography variant="h6" gutterBottom>
            Professional Information
          </Typography>
          <Grid container spacing={3}>
            <Grid item xs={12} sm={6}>
              <TextField
                id="degree"
                name="degree"
                label="Degree"
                fullWidth
                variant="standard"
                value={professionalInfo.degree || ""}
                onChange={handleChange}
              />
            </Grid>
            {professionalInfo?.workExperiences?.map((workExp, index) => (
              <Grid item xs={12} sm={6} key={index}>
                <TextField
                  id={`work-${index}`}
                  name="work"
                  label={`Experience ${index + 1}`}
                  fullWidth
                  variant="standard"
                  value={workExp.work || ""}
                  onChange={(e) => handleWorkChange(e, index)}
                />
                <DatePicker
                  selected={workExp.start}
                  onChange={(date) => handleWorkDateChange(date, index, "start")}
                  dateFormat="dd/MM/yyyy"
                  popperPlacement="bottom-start"
                />
                <DatePicker
                  selected={workExp.end}
                  onChange={(date) => handleWorkDateChange(date, index, "end")}
                  dateFormat="dd/MM/yyyy"
                  popperPlacement="bottom-start"
                />
                <Button onClick={() => handleRemoveWorkExperience(index)}>
                  Remove
                </Button>
              </Grid>
            ))}
            <Grid item xs={12}>
              <Button onClick={handleAddWorkExperience}>Add Work Experience</Button>
            </Grid>
            <Grid item xs={12} sm={6}>
              <TextField
                id="cert"
                name="cert"
                label="Certification"
                fullWidth
                variant="standard"
                value={professionalInfo.cert || ""}
                onChange={handleChange}
              />
            </Grid>
            <Grid item xs={12} sm={6}>
              <TextField
                id="skill"
                name="skill"
                label="Skills"
                fullWidth
                variant="standard"
                value={professionalInfo.skill || ""}
                onChange={handleChange}
              />
            </Grid>
            <Grid item xs={12} sm={6}>
              <TextField
                id="project"
                name="project"
                label="Personal Projects"
                fullWidth
                variant="standard"
                value={professionalInfo.project || ""}
                onChange={handleChange}
              />
            </Grid>
    
            <Grid item xs={12} sm={6}>
              <TextField
                id="linkedin"
                name="linkedin"
                label="Linkedin url"
                fullWidth
                variant="standard"
                value={professionalInfo.linkedin || ""}
                onChange={handleChange}
              />
            </Grid>
            <Grid item xs={12} sm={6}>
              <TextField
                id="accomp"
                name="accomp"
                label="write a paragraph on Your Accomplishments"
                fullWidth
                variant="standard"
                value={professionalInfo.accomp || ""}
                onChange={handleChange}
              />
            </Grid>
          </Grid>
          <Button onClick={handleSubmit}>Submit</Button>
          <Button onClick={handleReset}>Reset</Button>
        </>
      );
    };
    
    export default ProfessionalInfoUI;

professionalInfo.js:

// ProfessionalInfo.js
import React from "react";
import ProfessionalInfoUI from "./ProfessionalInfoUI";
import useProfessionalInfoForm from "./useProfessionalInfoForm";

const ProfessionalInfo = () => {
  const {
    professionalInfo,
    handleChange,
    handleWorkChange,
    handleWorkDateChange,
    handleAddWorkExperience,
    handleRemoveWorkExperience,
    handleSubmit,
    handleReset,
  } = useProfessionalInfoForm();

  return (
    <ProfessionalInfoUI
      professionalInfo={professionalInfo}
      handleChange={handleChange}
      handleWorkChange={handleWorkChange}
      handleWorkDateChange={handleWorkDateChange}
      handleAddWorkExperience={handleAddWorkExperience}
      handleRemoveWorkExperience={handleRemoveWorkExperience}
      handleSubmit={handleSubmit}
      handleReset={handleReset}
    />
  );
};

export default ProfessionalInfo;

Also I have wrote all my states in zustand: here is the code for that:

import create from "zustand";
import { devtools } from "zustand/middleware";
import { persist } from "zustand/middleware";

//  hook to manage zustand store. We are storing initial state in store and updating it when setPersonalInfo and resetPersonalInfo hooks are being called
const useProfessionalInfoStore = create(
  persist(
    devtools((set) => ({
      professionalInfo: {
        degree: "",
        workExperiences: [],
        cert: "",
        skill: "",
        project: "",
        linkedin: "",
        accomp: "",
      },
      setProfessionalInfo: (data, callback) => {
        set((state) => ({
          professionalInfo: { ...state.professionalInfo, ...data },
        }));
        if (callback && typeof callback === "function") {
          callback();
        }
      },
      resetProfessionalInfo: () => {
        set(() => ({
          professionalInfo: {
            degree: "",
            workExperiences: [],
            cert: "",
            skill: "",
            project: "",
            linkedin: "",
            accomp: "",
          },
        }));
      },
    })),
    {
      name: "professionalInfo-store", // Unique name for your store's persisted data
      getStorage: () => localStorage, // Choose your storage mechanism
    }
  )
);

export default useProfessionalInfoStore;

The problem is that When I extracted my business logic from UI. Nothing is working. Can someone please tell me what is the problem.

1

There are 1 best solutions below

1
Saurabh Sahni On

The issue might be related to how you are connecting the form logic with the UI component. There might be a problem with the way you are passing and using the props in your ProfessionalInfoUI component.

Additionally, it's a good idea to log the values and functions at different points in your components to debug and check if the values are being passed correctly. For example, add console.log statements in both the hook and the UI component to see if the values are as expected.

I hope this is helpfull.