在下一次渲染丢失数据时获取数据时的自定义钩子

时间:2021-01-28 16:43:18

标签: javascript reactjs optimization react-hooks

我做了一个钩子 useSendFormData ,当我使用它时,我得到了无效的钩子调用。

  • 钩取

  • 来自 SubmitForm 的数据

  • 网址:字符串,

  • 方法:发布或放置

  • success:如果成功则发送成功消息

  • id:不是必需的,但如果项目有 id,我会被添加到 api 调用中。

  • auth 默认为 false

问题是它丢失了渲染数据我不知道如何更好地描述它所以我制作了console.log ss 正如你在第二次通话中看到的,我得到了数据,但后来它消失了......

problem image

我的这个自定义钩子的代码:

    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,
  };
};

在哪里使用它,它从 SubmitForm 获取数据并使用它进行 api 调用,正如您在 ss 中看到的那样,我到达那里未定义:

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

如果您能提供帮助,那就太棒了。如果您对此挂钩有任何优化提示,请告诉我。感谢您抽出宝贵时间。

编辑:编辑钩子但最后不返回数据值

1 个答案:

答案 0 :(得分:1)

TL;DR

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

应该改为

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

说明

setState 回调可以采用新状态(你做了什么),或者另一个回调(应该做什么)。您应该像这样传递一个回调,以确保 setPartialData(someData) 内对 sendFormData 的多次调用使用最新的 data 状态来更新自身(结合 partialData)。这种方法是必要的,因为 const sendFormData = () => {} 已声明,其中使用的 data 变量是功能块外部的任何 data (来自 const [data, setData] = useState() )。此 data 不会在 sendFormData() 运行时更新,而是仅在组件渲染周期结束时更新。

换句话说,

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
}

请注意,您在哪里声明 const setPartData 并不重要,只要它可以访问 data 范围即可。

另一方面,

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

在需要运行 data 时使用最新的 setData() 状态,方法是通过内部回调访问它。

由于您构建的钩子可以返回 data 状态,因此一旦正确更新,您现在可以更好地使用它。

// 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 }
</>

this swr library 存在时重新发明轮子可能不是一个好主意,但我赞扬您努力使代码干燥。