React: Invalid hook call in SubmitForm, custom hook useSendFormData

Viewed 109

I made a hook useSendFormData, when I use it, I get Invalid hook call.

Hook takes

  • data from SubmitForm

  • url:string,

  • method: post or put

  • success: success message if it was successful

  • id: not required but if item has id i is added to api call.

Code:

     export const useSendFormData = async ({
              formData,
              url,
              method,
              success,
              id,
            }) => {
              const [data, setData] = useState({
                error: "",
                loading: true,
                success: "",
                data: [],
              });
              const setPartData = (partialData) => setData({ ...data, ...partialData });
              try {
                if (method === "post") {
                  const { data } = await axios.post(
                    `${SERVER_API}api/v1/${url}/${id ?? ""}`,
                    formData
                  );
                  setPartData({ data, success, error: null });
                } else if (method === "put") {
                  const { data } = await axios.post(
                    `${SERVER_API}api/v1/${url}/${id ?? ""}`,
                    formData
                  );
                  setPartData({ data, success, error: null });
                }
            
                setPartData({
                  loading: false,
                });
              } catch (err) {
                const { data } = err.response;
                setPartData({
                  error: data.error,
                  success: null,
                  loading: false,
                });
              }
              return {
                data,
              };
            };

I call it inside submit form, I don't know this matter but I use react-hook-forms for handling forms

    const sendFormData = useSendFormData

    const handleForm = async (info) => {
        const { data } = await sendFormData({
          formData: info,
          url: "auth/forgot-password",
          method: "post",
          success: "A password reset message has been sent to your email",
        });
    
        console.log(data);
    
        reset();
      };

If I change

const sendFormData = useSendFormData

to

const sendFormData = useSendFormData()

I get an error:

Cannot destructure property 'formData' of 'undefined' as it is undefined

How can I make this work and if you see any way of improving this custom hook I would be very grateful for your help and time.

1 Answers

The way you designed your hook the fetch is done once the hook is invoked. Instead you should define a sendFormData function inside your hook and return it along with data state (or any other variables you need). Since you want response.data to be returned I adapted the function to return response.data:

export const useSendFormData = () => {
  const [data, setData] = useState({
    error: "",
    loading: true,
    success: "",
    data: [],
  });

  const sendFormData = async ({
    formData,
    url,
    method,
    success,
    id,
  }) => {
    const setPartData = (partialData) => setData({ ...data, ...partialData });
    try {
      let response
      if (method === "post") {
        response = await axios.post(
          `${SERVER_API}api/v1/${url}/${id ?? ""}`,
          formData
        );
        setPartData({ data: response.data, success, error: null });
      } else if (method === "put") {
        response = await axios.post(
          `${SERVER_API}api/v1/${url}/${id ?? ""}`,
          formData
        );
        setPartData({ data: response.data, success, error: null });
      }
      setPartData({
        loading: false,
      });
      return response.data

    } catch (err) { 
      const { data } = err.response;
      setPartData({
        error: data.error,
        success: null,
        loading: false,
      });
      return data
    }
  }

  return {
    data, sendFormData
  };
};

With that you can call your hook properly at your component body, extracting data and sedFormData:

// here you have your data state and sendFormData extracted
const { data, sendFormData } = useSendFormData()


const handleForm = async (info) => {
  // here you have your response.data returned
  const data = await sendFormData({
    formData: info,
    url: "auth/forgot-password",
    method: "post",
    success: "A password reset message has been sent to your email",
  });

  console.log(data);

  reset();
};
Related