javascriptreactjsreact-suspense

Trying to implement React Suspense boundary and refetching data from API after some events


Hey im pretty new to React and JS.

Im trying to implement the React Suspense boundary for a component that requires fechting data from my backend API. I used the fetchData and wrapPromise function from this example [https://dev.to/darkmavis1980/a-practical-example-of-suspense-in-react-18-3lln](A practical example of Suspense in React 18 ).

wrapPromise function:

/**
 * Wraps a promise so it can be used with React Suspense
 * @param {Promise} promise The promise to process
 * @returns {Object} A response object compatible with Suspense
 */
function wrapPromise(promise) {
  let status = "pending";
  let response;

  const suspender = promise.then(
    (res) => {
      status = "success";
      response = res;
    },
    (err) => {
      status = "error";
      response = err;
    }
  );

  const handler = {
    pending: () => {
      throw suspender;
    },
    error: () => {
      throw response;
    },
    default: () => response,
  };

  const read = () => {
    const result = handler[status] ? handler[status]() : handler.default();
    return result;
  };

  return { read };
}

export default wrapPromise;

fetchData function:

 * Wrap Axios Request with the wrapPromise function
 * @param
 * @returns {Promise} A wrapped promise
 */
function fetchData(url) {
  const promise = axios.get(url).then(({ data }) => data);

  return wrapPromise(promise);
}

export default fetchData;

So i created a component RecipeTableMain to render the recipe data:

import fetchData from "../../api/fetchData";

const resource = fetchData("http://localhost:3001/recipes");
...

export default function RecipeTableMain() {
  const data = resource.read(); //Calling read function from wrapPromise

... some code for mui data grid
}

My Problem is: The data only gets fetched on the first render of RecipeTableMain component (After i reload my app). I tried to find a way to fetch the data again for example after deleting or creating a new recipe, but i have no idea how i could implement this in my code.

Thanks Jonas.

I think i missed some basics about how code outside of React components is executed.


Solution

  • Like the user from this post:

    Infinite loop when using React Suspense and Axios data fetch

    I ditched the wrapPromise() function, and used the useSWR hook instead.

    I also modified the fetchData() function:

    import axios from "axios";
    
    /**
     * Wrap Axios Request with the wrapPromise function
     * @param {String} URL Endpoint
     */
    async function fetchData(url) {
      return axios
        .get(url)
        .then(({ data }) => data)
        .catch((err) => console.log(err));
    }
    
    export default fetchData;
    

    And i call it like this:

    import useSWR from "swr";
    import fetchData from "../../api/fetchData";
    
    export default function RecipeTableMain() {
    
      const url = "http://localhost:3001/recipes";
      const fetcher = (url) => fetchData(url);
      const { data } = useSWR(url, fetcher, {
        suspense: true,
      });
    ...
    }
    

    Now the data gets fetched on every render of the component and i can also pass an route id from react router if necessary.