Skip to content

Instantly share code, notes, and snippets.

@mauricedb
Last active January 18, 2020 10:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauricedb/cf1ebd484d07462ca343892cf408c68a to your computer and use it in GitHub Desktop.
Save mauricedb/cf1ebd484d07462ca343892cf408c68a to your computer and use it in GitHub Desktop.
useAbortableFetch
import React, { useState } from 'react';
import useAbortableFetch from './useAbortableFetch';
const Joke = () => {
const { json: joke, loading, error, abort } = useAbortableFetch(
'http://api.icndb.com/jokes/random/?limitTo=[nerdy]&escape=javascript'
);
if (loading) return 'Loading...';
if (error) return 'Error: ' + error;
if (!joke) return null;
return <div>{joke.value.joke}</div>;
};
export default Joke;
import { useState, useEffect } from 'react';
const fetchData = async (url, signal, setState) => {
try {
const rsp = await fetch(url, { signal });
const json = await rsp.json();
setState(oldState => ({
...oldState,
json,
loading: false
}));
} catch (err) {
const error = err.name !== 'AbortError' ? err.message : null;
setState(oldState => ({
...oldState,
error,
loading: false
}));
}
};
const useAbortableFetch = url => {
const [state, setState] = useState({
json: null,
loading: false,
error: null,
controller: null
});
useEffect(
() => {
const controller = new AbortController();
setState({
json: null,
loading: true,
error: null,
controller
});
fetchData(url, controller.signal, setState);
return () => controller.abort();
},
[url]
);
return {
json: state.json,
loading: state.loading,
error: state.error,
abort: () => state.controller && state.controller.abort()
};
};
export default useAbortableFetch;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment