10

Im mostly using SWR to get data, however I have a situation that I need to update data. The problem is, I need an indicator that this request is ongoing, something like isLoading flag. In the docs there's a suggestion to use

const isLoading = !data && !error;

But of course when updating (mutating) the data still exists so this flag is always false. The same with isValidating flag:

const { isValidating } = useSWR(...);

This flag does NOT change when mutation is ongoing but only when its done and GET request has started.

Question

Is there a way to know if my PUT is loading? Note: I dont want to use any fields in state because it won't be shared just like SWR data is. Maybe Im doing something wrong with my SWR code?

const fetcher = (url, payload) => axios.post(url, payload).then((res) => res); 
  // ^^^^^ its POST but it only fetches data

const updater = (url, payload) => axios.put(url, payload).then((res) => res);
  // ^^^^^ this one UPDATES the data

const useHook = () => {
  const { data, error, mutate, isValidating } = useSWR([getURL, payload], fetcher);

  const { mutate: update } = useSWRConfig();

  const updateData = () => {
    update(getURL, updater(putURL, payload)); // update data
    mutate(); // refetch data after update
  };

  return { 
    data,
    updateData,
    isValidating,               // true only when fetching data
    isLoading: !data && !error, // true only when fetching data
  } 

Edit: for any other who reading this and facing the same issue... didnt find any solution for it so switched to react-query. Bye SWR

underfrankenwood
  • 431
  • 1
  • 7
  • 22
  • 1
    I think you should not use a loading indicator after a mutation, an optimstic update is much better from a UX pov. I think you are doing something wrong, not sure how you are handling fetching and data update, but there's something not good. The second parameter function of *mutate* should be a function to update the cache while you are passing another fetcher. Then use a post call to perform a refetch ? Try to stick with a simple Query -> mutate -> optimistic update -> revalidate pattern. – Cesare Polonara May 22 '22 at 20:51
  • @CesarePolonara thanks, I will try that. However I really need this indicator, this is what users of my application are used to. – underfrankenwood May 22 '22 at 21:38
  • @CesarePolonara consider the next use case: refresh mobile screen with your finger (the down gesture) - you want the screen to show loading indicator while fetching the data again. – chenop Aug 02 '22 at 20:33
  • @underfrankenwood any conclusions? – chenop Aug 02 '22 at 20:34
  • @chenop The scroll refresh is a GET query it's not related to the OP's question which regards a PUT mutation... – Cesare Polonara Aug 04 '22 at 15:00

3 Answers3

0
const { mutate: update } = useSWRConfig();

  const updateData = () => {
    // this will return promise
    update(getURL, updater(putURL, payload)); // update data
    mutate(); // refetch data after update
  };

By using react-toastify npm module to show the user status.

// first wrap your app with: import { ToastContainer } from "react-toastify";

 import { toast } from "react-toastify";

 const promise=update(getURL, updater(putURL, payload))

 await toast.promise(promise, {
    pending: "Mutating data",
    success: "muttation is successfull",
    error: "Mutation failed",
  });
Yilmaz
  • 35,338
  • 10
  • 157
  • 202
0
const markSourceMiddleware = (useSWRNext) => (key, fetcher, config) => {
    const nextFetcher = (...params) =>
        fetcher(...params).then((response) => ({
            source: "query",
            response,
        }));

    const swr = useSWRNext(key, nextFetcher, config);
    return swr;
};

const useHook = () => {
    const {
        data: { source, response },
        mutate,
    } = useSWR(key, fetcher, { use: [markSourceMiddleware] });

    const update = mutate(
        updateRequest().then((res) => ({
            source: "update",
            response,
        })),
        {
            optimisticData: {
                source: "update",
                response,
            },
        }
    );

    return {
        update,
        updating: source === "update",
    };
};
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 11 '22 at 01:09
-3

Hmm based on that: https://swr.vercel.app/docs/conditional-fetching

It should work that the "is loading" state is when your updater is evaluates to "falsy" value.

REMAINDER! I don't know react swr just looked into docs - to much time at the end of the weekend :D

At least I hope I'll start discussion :D

user432281
  • 11
  • 1