0

enter image description here

In this code I was trying to update superadmin by their id. After clicking on the edit button a form will open and all data of superadmin will show in the input field for that I used the loadAdmin function to get all data from API and show it in input but after making some changes in the input field and set modified form data to API for updating I am getting 404 axios error message and I see undefined in superAdmin fields. I've attached the Postman form-data Screenshot. Please Assist me how to solve this issue

import axios from "axios";
import { useCallback, useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { FiEye } from "react-icons/fi";

const EditAdmin = () => {
  const { id } = useParams();

  const [EditSuperAdmin, setEditSuperAdmin] = useState({
    profilePhoto: null,
    password: "",
    superAdmin: {
      firstName: "",
      lastName: "",
      mobileNumber: "",
      phoneNumber: "",
      lastModifiedBy: "",
    },
  });

  const [show, setShow] = useState(false);

  // function to handle input changes
  const handleChange = (e) => {
    const { name, value } = e.target;
    setEditSuperAdmin((prevState) => ({
      ...prevState,
      [name]: value,
    }));
  };

  // function to handle logo file input change
  const handleLogoChange = (e) => {
    setEditSuperAdmin((prevState) => ({
      ...prevState,
      profilePhoto: e.target.files[0],
    }));
  };

  // Update SuperAdmin
  const handleSubmit = async (e) => {
    e.preventDefault();

    const formData = new FormData();
    formData.append('profilePhoto' , EditSuperAdmin.profilePhoto)
    formData.append('password' , EditSuperAdmin.password)
    formData.append('superAdmin' , JSON.stringify(EditSuperAdmin.superAdmin))
    console.log(Object.fromEntries(formData))

    try {
      await axios
        .put(`/superAdmin/updateById/${id}`, formData, {
          headers: { "Content-Type": "multipart/form-data" },
        })
        .then((res) => {
          console.log(res.data[0]);
          navigate("/superAdmin");
        });
    } catch (error) {
      console.log(error);
    }
  };

  const loadAdmin = useCallback(async () => {
    const response = await axios.get(
      `/superAdmin/allsuperAdminById/${id}`
    );
    console.log(response.data);
    setEditSuperAdmin(response.data[0]);
  }, [id]);

  useEffect(() => {
    loadAdmin();
  }, [loadAdmin]);

  const navigate = useNavigate();
  const handleClose = () => {
    navigate(-1);
  };

  const inputClassName =
    "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500";
  return (
    <>
      <div className="fixed z-50 backdrop-blur-md bg-white/10 top-0 left-0 right-0  bottom-0 "></div>
      <div className=" bg-gray-900 h-[70%] overflow-y-auto text-white md:top-[50%] md:w-1/3 w-full px-10 py-5 top-[40%] left-[50%] rounded-2xl transform translate-x-[-50%]  translate-y-[-50%] fixed z-50">
        <h2 className="text-[2rem]">Edit Admin</h2>
        <hr className="mb-3" />
        <form onSubmit={handleSubmit}>
          <div className="mb-6">
            <label
              className="block mb-2 text-sm font-medium text-white dark:text-black"
              htmlFor="profile photo"
            >
              Profile Photo
            </label>
            <input
              className="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400"
              aria-describedby="user_avatar_help"
              type="file"
              name="profilePhoto"
              onChange={handleLogoChange}
            />
          </div>
          <div className="mb-6">
            <label
              htmlFor="first name"
              className="block mb-2 text-sm font-medium text-white dark:text-black"
            >
              First Name
            </label>
            <input
              type="text"
              className={inputClassName}
              placeholder="first Name"
              required
              onChange={handleChange}
              name="firstName"
              value={EditSuperAdmin.firstName}
            />
          </div>
          <div className="mb-6">
            <label
              htmlFor="last Name"
              className="block mb-2 text-sm font-medium text-white dark:text-black"
            >
              Last Name
            </label>
            <input
              type="text"
              className={inputClassName}
              placeholder="last Name"
              required
              onChange={handleChange}
              name="lastName"
              value={EditSuperAdmin.lastName}
            />
          </div>
          <div className="mb-6">
            <label
              htmlFor="password"
              className="block mb-5 text-sm font-medium text-white dark:text-black"
            >
              Password
            </label>
            <div className="flex justify-center items-center relative">
              <input
                type={show ? "text" : "password"}
                className={`${inputClassName}, absolute`}
                placeholder=""
                // required
                onChange={handleChange}
                name="password"
                value={EditSuperAdmin.password}
              />
              <FiEye
                onClick={() => setShow(!show)}
                className="absolute cursor-pointer text-black right-[0.5rem]"
              />
            </div>
          </div>
          <div className="mb-6">
            <label
              htmlFor="mobile number"
              className="block mb-2 text-sm font-medium text-white dark:text-black"
            >
              Mobile Number
            </label>
            <input
              type="tel"
              className={inputClassName}
              placeholder="+123456789"
              required
              name="mobileNumber"
              onChange={handleChange}
              value={EditSuperAdmin.mobileNumber}
            />
          </div>
          <div className="mb-6">
            <label
              htmlFor="phone number"
              className="block mb-2 text-sm font-medium text-white dark:text-black"
            >
              Phone Number
            </label>
            <input
              type="tel"
              className={inputClassName}
              placeholder="+123456789"
              required
              name="phoneNumber"
              onChange={handleChange}
              value={EditSuperAdmin.phoneNumber}
            />
          </div>
          <div className="mb-6">
            <label
              htmlFor="last modified by"
              className="block mb-2 text-sm font-medium text-white dark:text-black"
            >
              Last Modified By
            </label>
            <input
              type="text"
              className={inputClassName}
              placeholder=""
              required
              name="lastModifiedBy"
              onChange={handleChange}
              value={EditSuperAdmin.lastModifiedBy}
            />
          </div>
          <div className="flex justify-around">
            <button
              type="submit"
              className="text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
            >
              Update
            </button>
            <button
              onClick={handleClose}
              type="submit"
              className="text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm  px-5 py-2.5 text-center dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-blue-800"
            >
              Cancel
            </button>
          </div>
        </form>
      </div>
    </>
  );
};

export default EditAdmin;

I'd Appreciate Some help! Thanks

Phil
  • 157,677
  • 23
  • 242
  • 245
Prince
  • 25
  • 9
  • You're making the request to a relative path, have you set a `baseURL` in Axios? Use your browser's dev-tools _Network_ panel to check that the request is being made to the right location – Phil May 22 '23 at 23:21
  • FYI you don't need the `content-type` header and setting it can often lead to problems. See [this answer](https://stackoverflow.com/a/68643919/283366) for details – Phil May 22 '23 at 23:22
  • Yes, I've set baseURL in app.js – Prince May 23 '23 at 06:06

1 Answers1

1

Your handleChange function sets properties at the top level of EditSuperAdmin but you appear to want everything other than profilePhoto and password nested within a superAdmin property.

I think you'd be best working with a flat structure and marshalling / unmarshalling it where required.

For example

const [EditSuperAdmin, setEditSuperAdmin] = useState({
  profilePhoto: null,
  password: "",
  firstName: "",
  lastName: "",
  mobileNumber: "",
  phoneNumber: "",
  lastModifiedBy: "",
});

// no need to overcomplicate this with useCallback
useEffect(() => {
  axios
    .get(`/superAdmin/allsuperAdminById/${id}`)
    .then(({ data: [{ superAdmin, ...rest }] }) => {
      // flatten the data
      setEditSuperAdmin({
        ...rest,
        ...superAdmin,
      });
    })
    .catch(console.error);
}, [id]);

const handleSubmit = async (e) => {
  e.preventDefault();

  // extract properties
  const { profilePhoto, password, ...superAdmin } = EditSuperAdmin;

  const formData = new FormData();
  formData.append("profilePhoto", profilePhoto);
  formData.append("password", password);
  formData.append("superAdmin", JSON.stringify(superAdmin));

  try {
    // don't mix await with .then()
    const { data } = await axios.put(`/superAdmin/updateById/${id}`, formData);
    console.log("[handleSubmit] response:", data[0]);
    navigate("/superAdmin");
  } catch (error) {
    console.log(error);
  }
};

As an aside, it seems your API responds with arrays, even for single objects. I'd strongly suggest not doing this.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • Thank you for your answer. now I can see all form details in the console after clicking on the update before "undefined" was showing for superAdmin .now it's showing all modified data on the console and network section. but after an update, it's showing a 405 error with the message "Method 'PUT' is not supported.". FYI there is no typo I have written axios.put. why it's showing this error. Trace:org.springframework.web.HttpRequestMethodNotSupportedException . as a fresher it's really difficult for me to solve this kind of problem. thank you for your help. – Prince May 23 '23 at 06:15
  • @Prince seems that the API you're calling doesn't support a PUT request. I assumed from your question that you had tested it with Postman but now that doesn't seem the case – Phil May 23 '23 at 06:30
  • Sorry actually I passed the wrong URL for updation that's why it was showing method PUT not supported. there is a separate API for updates. sorry to disturb you. – Prince May 23 '23 at 08:19