skip to Main Content

I have a api that only uses POST, so i have to sent an ID to fetch, in this case event.

The problem is that my SWR is making infinite calls.

I have this component:

const EventDetail = ({ params }: { params: { id: string } }) => {
  const id: string = params.id;
  const [cookies] = useCookies(["token"]);

  const token = cookies.token;
  let formData = new FormData();
  formData.append("id", id);
  const dataToRequest = { token, formData };
  const { data, error, isLoading } = useSWR(
    [SERVICESADDR.EVENT, dataToRequest],
    fetcher,
  );
  if (error) {
    console.log(error);
  }
  console.log(data);

  return <div>{id}</div>;
};

export default EventDetail;

and my fetcher is:

export const fetcher = ([url, data]: [
  url: string,
  data: { token: string; formData?: FormData },
]) =>
  fetch(url, {
    method: "POST",
    body: data.formData,
    headers: {
      Authorization: `Bearer ${data.token}`,
      "Accept-Language": "pt",
      Accept: "/*",
    },
  })
    .then((res) => res.text())
    .then((res) => res);

Thank you in advance!!

2

Answers


  1. Try turning the FormData object into a plain old JS object before using it as a value in the SWR key. It’s unclear from useSWR‘s "Passing Objects" docs, but it might not be serializing it as expected and therefore seeing a new object on every render and always thinking the cache key has changed:

    const dataToRequest = { token, formData: Object.fromEntries(formData) };
    
    Login or Signup to reply.
  2. This is because the key (first arguement of useSWR) is tied to the cache key.
    If any value in this array is updated, a new http request will be triggered.

    In your example, the key is [SERVICESADDR.EVENT, dataToRequest] and dataToRequest is recreated at each render (you create a new FormData object), that’s why you get an infinite service call.

    You can pass the token and the id to key and create the FormData object in the fetcher function

    const EventDetail = ({ params }: { params: { id: string } }) => {
      const id: string = params.id;
      const [cookies] = useCookies(["token"]);
      const token = cookies.token;
      const { data, error, isLoading } = useSWR(
        [SERVICESADDR.EVENT, token, id],
        fetcher,
      );
    
      return <div>{id}</div>;
    };
    
    export const fetcher = ([url, token, id]: [
      url: string,
      token: string,
      id: string
    ]) => {
      const formData = new FormData();
      formData.append("id", id);
    
      return fetch(url, {
        method: "POST",
        body: formData,
        headers: {
          Authorization: `Bearer ${token}`,
          "Accept-Language": "pt",
          Accept: "/*",
        },
      }).then((res) => res.text());
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search