Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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: succes message if it was success

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

  • auth default false

Problem is it loses data on renders i dont know how to describe it better so i made console.log ss As you can see on second call i get data but later its gone...

problem image

My code for this coustom hook:

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

  return {
    sendFormData,
  };
};

And where is use it , it takes data from SubmitForm and make api call with it,as you can see in ss i get there undefined:

const { 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();
};

If you could help that would be awesome. If you have any optimatizaion hints for this hook please tell me.Thanks for your time.

Edit: Edit hook but doesnt return data value at the end

question from:https://stackoverflow.com/questions/65941485/coustom-hook-when-taking-data-in-next-render-lost-data

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
95 views
Welcome To Ask or Share your Answers For Others

1 Answer

TL;DR

const setPartData = (partialData) => setData({ ...data, ...partialData });

should be changed to

const setPartData = (partialData) => setData(data => ({ ...data, ...partialData }));

Explanation

setState callback can take either the new state (what you have done), or another callback (what should be done). You should pass a callback like so, to make sure that multiple calls of setPartialData(someData) within sendFormData uses the latest data state to update itself (combining partialData). This approach is necessary as const sendFormData = () => {} is declared, the data variable used within is whatever data was outside the function block (from const [data, setData] = useState() ). This data is not updated as sendFormData() runs, instead only on the end of a component render cycle.

In other words,

const [data, setData] = useState(initialData);

const sendFormData = () => {
  const setPartData = (partialData) => setData({ ...data, ...partialData });
  setPartData(data1); // combines with initialData
  setPartData(data2); // combines with initialData as well
}

Note that where you declare const setPartData does not matter, as long as it has access to the data scope.

On the other hand,

const setPartData = (partialData) => setData(data => ({ ...data, ...partialData }));

uses the latest data state when setData() needs to run, by accessing it through the internal callback.

Since the hook you built can return the data state, once it is updated correctly, you can now use it like this in a better manner.

// App.js
const {data, sendFormData} = useSendFormData();

const sendAction = async (arg) => await sendFormData(arg);

return <>
  <button onClick={sendAction}>send data</button>
  { data.success || someCondition ? data : null }
</>

It's probably not a good idea to reinvent the wheel when this swr library exists, but I commend your effort in trying to make code DRY.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...