Skip to content

Instantly share code, notes, and snippets.

@quisido
Created November 1, 2018 01:03
Show Gist options
  • Save quisido/8df1bd1dbc1fe611df803c877d4e2815 to your computer and use it in GitHub Desktop.
Save quisido/8df1bd1dbc1fe611df803c877d4e2815 to your computer and use it in GitHub Desktop.
React Suspense with the Fetch API
const deepEqual = require('deep-equal');
interface FetchCache {
fetch?: Promise<void>;
error?: any;
init: RequestInit | undefined;
input: RequestInfo;
response?: any;
}
const fetchCaches: FetchCache[] = [];
const useFetch = (input: RequestInfo, init?: RequestInit | undefined) => {
for (const fetchCache of fetchCaches) {
// The request hasn't changed since the last call.
if (
deepEqual(input, fetchCache.input) &&
deepEqual(init, fetchCache.init)
) {
// If we logged an error during this fetch request, THROW the error.
if (Object.prototype.hasOwnProperty.call(fetchCache, 'error')) {
throw fetchCache.error;
}
// If we received a response to this fetch request, RETURN it.
if (Object.prototype.hasOwnProperty.call(fetchCache, 'response')) {
return fetchCache.response;
}
// If we do not have a response or error, THROW the promise.
throw fetchCache.fetch;
}
}
// The request is new or has changed.
const fetchCache: FetchCache = {
fetch:
// Make the fetch request.
fetch(input, init)
// Parse the response.
.then(response => {
// Support JSON.
if (Object.prototype.hasOwnProperty.call(response.headers, 'Content-Type')) {
return response.json();
}
// Not JSON.
return response.text();
})
// Cache the response for when this component
// attempts to render again later.
.then(response => {
fetchCache.response = response;
})
// Cache the error for when this component
// attempts to render again later.
.catch(e => {
fetchCache.error = e;
}),
init,
input
};
// Add this metadata to the memoization array.
fetchCaches.push(fetchCache);
// Throw the Promise! Suspense to the rescue!
throw fetchCache.fetch;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment