skip to Main Content

I have following code

const useCreateSupplier = (createSupplierCommand: CreateSupplierCommand) => {
  return useMutation({
    mutationFn: () =>
      axiosClient
        .post("/supplier", { createSupplierCommand })
        .then((res: AxiosResponse) => res.data),
    onSuccess: async () => {
      await queryClient.invalidateQueries({
        queryKey: [queries.get_suppliers],
      });
    },
  });
};
const CreateSupplierForm = () => {
  const useSubmit = (event: any) => {
    event.preventDefault();
    useCreateSupplier({ name: "x", website: "xxx" });
  };

  return (
    <>
      <form className="row mt-3 mb-4" onSubmit={useSubmit}>
        <div className="col-auto">
          <input type="text" className="form-control" placeholder="name" />
        </div>
        <div className="col-auto">
          <input type="text" className="form-control" placeholder="website" />
        </div>
        <div className="col-auto d-flex align-items-center">
          <button type="submit" className="btn btn-sm btn-primary">
            Add
          </button>
        </div>
      </form>
    </>
  );
};

but the page render following error

Invalid hook call. Hooks can only be called inside of the body of a
function component. This could happen for one of the following
reasons:

How can I call mutation after the form is submitted?

2

Answers


  1. The error is pretty clear:

    First move the hook definition inside the body of your functional component

       const CreateSupplierForm = () => {
        
            const useCreateSupplier = (createSupplierCommand:CreateSupplierCommand) => {
            return useMutation({
                mutationFn: () => axiosClient.post('/supplier', { createSupplierCommand }).then((res: AxiosResponse) => res.data),
                onSuccess: async() => { await queryClient.invalidateQueries({ queryKey: [queries.get_suppliers] }) }
            })}
           ...
    

    Then you don’t really need the useSubmit function as react-query already contains all the logic while dealing with mutations

    Just call the mutation with your form values with something like this

    <form className="row mt-3 mb-4" onSubmit={(values) => useCreateSupplier(values)}>
    
    Login or Signup to reply.
  2. I recommend you read up on what hooks are and how to use them.

    useSubmit is not a hook and therefore it shouldn’t start with the word use. I’ll call it onSubmit instead.

    As the message says hooks (like useCreateSupplier) need to be called in the function body, so we move it there.

    According to the docs, useMutation returns an object, and to actually trigger the API call we need to call mutate (or mutateAsync) of that object.

    const CreateSupplierForm = () => {
       const mutation = useCreateSupplier({ name: 'x', website: 'xxx' });
    
       const onSubmit = () => {
           mutation.mutate()
       }
    
       return (
           <>
               <form className="row mt-3 mb-4" onSubmit={onSubmit}>
                   <div className="col-auto">
                       <input type="text" className="form-control" placeholder="name" />
                   </div>
                   <div className="col-auto">
                       <input type="text" className="form-control" placeholder="website" />
                   </div>
                   <div className="col-auto d-flex align-items-center">
                       <button type="submit" className="btn btn-sm btn-primary">Add</button>
                   </div>
               </form>
           </>)
    }
    

    Apart from this, to call the form with your input, you will need to do some addional changes, e.g. storing the input in some kind of state. Here’s some reading on how to combine forms with Tanstack Query (React Query).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search