Search code examples
javascriptreactjstypescriptreact-hook-formrtk-query

error 400 bad request with form in react and RTKQ


i have a form that i want to add or update an item with it. for both adding and updating i use POST request. if i have a id param in my url i want to update the item and if there is no id i want to add item. for adding every thing works fine but when i want to update i got 400 bad request that says some of my form data are required. i used same structure for my form data in adding item that worked fine.

import Button from "@/components/utils/button/button.component";
import { InputController } from "@/components/utils/input/input-controller.component";
import Modal from "@/components/utils/modal/modal.component";
import { TextAreaController } from "@/components/utils/textarea/textarea-controller.component";
import {
  useAddComplianceRequirementMutation,
  useGetComplianceRequirementByIdQuery,
  useUpdateComplianceRequirementMutation,
} from "@/infrastructure/slice/compliance-requirement.slice";
import { useForm } from "react-hook-form";
import { useParams } from "react-router-dom";

type Props = {
  onClose: () => void;
};
const AddRequirementsGroupModal: React.FC<Props> = ({ onClose }) => {
  const { control, handleSubmit } = useForm();
  const { complianceId, id } = useParams();

  const [addRequirement, { isLoading: isAddLoading }] =
    useAddComplianceRequirementMutation();
  const [updateComplianceRequirement, { isLoading: isUpdateLoading }] =
    useUpdateComplianceRequirementMutation();

  const { data: groupData, isLoading } = useGetComplianceRequirementByIdQuery(
    { id },
    { skip: !id }
  );

  const onSubmit = handleSubmit(async (data) => {
    const sendData = {
      ...data,
      packageId: complianceId,
      type: 1,
      complianceId,
    };
    try {
      if (id) {
        await updateComplianceRequirement({
          ...sendData,
          id,
        });
        onClose();
      } else {
        await addRequirement(sendData);
        onClose();
      }
    } catch (e) {
      console.log(e);
    }
  });

  return (
    <>
      <Modal
        isOpen
        onClose={onClose}
        title="اضافه کردن گروه الزامات"
        isLoading={isLoading}
      >
        <form onSubmit={onSubmit}>
          <InputController
            control={control}
            name="label"
            label="عنوان گروه الزامات"
            requiredInput
            rules={{ required: "لطفا عنوان گروه الزامات را وارد کنید." }}
            defaultValue={groupData?.label}
          />
          <TextAreaController
            control={control}
            name="title"
            defaultValue={groupData?.title}
          />
          <div className="flex gap-2">
            <InputController
              control={control}
              name="value"
              label="وزن گروه الزامات"
              requiredInput
              rules={{ required: "لطفا وزن گروه الزامات را وارد کنید." }}
              type="number"
              defaultValue={groupData?.value}
            />
            <InputController
              control={control}
              name="code"
              label="کد"
              requiredInput
              rules={{ required: "لطفا فصل گروه الزامات را مشخص کنید." }}
              defaultValue={groupData?.code}
            />
          </div>
          <TextAreaController
            control={control}
            name="description"
            label="توضیحات گروه الزامات"
            defaultValue={groupData?.description}
          />
          <div className="flex justify-start gap-2">
            <Button size="sm" loading={isAddLoading || isUpdateLoading}>
              ثبت گروه
            </Button>
            <Button color="danger" onClick={onClose}>
              انصراف
            </Button>
          </div>
        </form>
      </Modal>
    </>
  );
};

export default AddRequirementsGroupModal;

and if it helps hera are my add request:

 addComplianceRequirement: builder.mutation({
      query: (body) => ({
        url: "/packageitem",
        method: "POST",
        body,
      })

and this is my update request :

 updateComplianceRequirement: builder.mutation({
      query: ({ id, body }) => ({
        url: `/packageitem/${id}`,
        method: 'POST',
        body,
      })

Solution

  • The problem is here...

    await updateComplianceRequirement({
      ...sendData,
      id,
    });
    

    This will create a payload like

    {
      "id": 1,
      "code": "some code",
      "label": "some label",
      ...
    }
    

    but your updateComplianceRequirement mutation is looking for an object with two properties; id and body.

    Simply place the sendData into a body property when constructing the payload

    await updateComplianceRequirement({ id, body: sendData });
    

    or change your mutation to something like

    updateComplianceRequirement: builder.mutation({
      query: ({ id, ...body }) => ({ // spread the rest into `body`
        url: `/packageitem/${id}`,
        method: 'POST',
        body,
      })