Search code examples
reactjsaxiosreact-hookses6-promise

using axios with promise API


I am using a promise based hook in a React app to fetch async data from an API.

I am also using a Axios, a promise based http client to call the API.

Is it an anti-pattern to use a promise based client inside another promise? The below code does not seem to work.

const getData = () => {
  return new Promise((resolve, reject) => {
    const url = "/getData";
    axios.get(url)
      .then(function(response) {
        resolve(response);
      })
      .catch(function(error) {
        reject(error);
      });
  });

const useAsync = (asyncFunction) => {
  const [value, setValue] = useState(null);

  const execute = useCallback(() => {
    setPending(true);
    setValue(null);
    setError(null);
    return asyncFunction()
      .then(response => setValue(response))
      .catch(error => setError(error))
      .finally(() => setPending(false));
  }, [asyncFunction]);

  useEffect(() => {
      execute();
  }, [execute]);

  return { execute, pending, value, error };
};
};

const RidesList = () => {
  const {
    pending,
    value,
    error,
  } = useAsync(getData);

Solution

  • Oh man. I think you have a fundamental misunderstanding about how Promises work. First, axios already returns a Promise by default. So your whole first function of getData can be reduced to:

    const getData = () => {
      const url = "/getData"
      return axios.get(url)
    }
    

    But the meat of your code seems to indicate you want a querable Promise - so you can check the status of it for whatever reason. Here's an example of how you would do it, adapted from this snippet:

    function statusPromiseMaker(promise) {
      if (promise.isResolved) return promise
      let status = {
        pending: true,
        rejected: false,
        fulfilled: false
      }
      let result = promise.then(
          resolvedValue => {
            status.fulfilled = true
            return resolvedValue
          },
          rejectedError => {
            status.rejected = true
            throw rejectedError
          }
        )
        .finally(() => {
          status.pending = false
        })
    
      result.status = () => status
      return result
    }
    

    In this way, you can then do something like let thing = statusPromiseMaker(getData()) and if you look up thing.status.pending you'll get true or false etc...

    I didn't actually run what's above, I may have forgotten a bracket or two, but hopefully this helps.

    I have to admit - I haven't seen anything like this ever used in the wild. I am interested in knowing what you're actually trying to accomplish by this.