Skip to content

Instantly share code, notes, and snippets.

@isocroft
Last active June 16, 2020 13:15
Show Gist options
  • Save isocroft/1de349e7abf868618b5eedf4059a660e to your computer and use it in GitHub Desktop.
Save isocroft/1de349e7abf868618b5eedf4059a660e to your computer and use it in GitHub Desktop.
A React Hook for fetching data and notifying all other components
import { useState } from 'preact/hooks';
import fetch from 'isomorphic-fetch';
/**
* `useSync` was created to abstract the stateful logic for managing rest/graphql
* requests ( fetches / queries / mutations ) in such a manner as to not repeat similar logic
* in different components across the project and to be made instantly reusable in
* these components. The implementation is highly functional
* ( lots of function composition and argument currying ).
*
* Also, `useFetch` was created to abstract the implementation of the `isLoading` state
* of any component very trivial (while the component is waiting for data from the
* server [ queries ] OR while the component is waiting for data being sent to the
* server to be fulfilled [ mutations ]) which i believe is crucial to presenting
* visual cues for pending activity to the end user.
*
* @param {mixed} defaultFetchData
* @param {mixed} defaultFetchError
* @param {Function} customizePayload
*
* @returns {Object}
*/
const useFetch = (
defaultFetchData = null,
defaultFetchError = null,
customizePayload = r => {
return r;
}
) => {
const [fetchData, setFetchData] = useState(defaultFetchData);
const [fetchError, setFetchError] = useState(defaultFetchError);
const [isPending, setIsPending] = useState(true);
const _fetch = (urlOrQuery, params = null) => {
setIsPending(true);
return fetch(urlOrQuery, params)
.then(function onData(payload) {
if (payload.error) throw payload.error;
setFetchData(customizePayload(payload.response, 'response'));
return emitToAll(urlOrQuery, payload.response);
})
.catch(function onError(payload) {
setFetchError(
customizePayload(
payload instanceof Error ? payload : payload.error,
'error'
)
);
})
.finally(function onFinish() {
setIsPending(false);
});
};
const connectToFetcher = templateFunction => {
return typeof templateFunction === 'function'
? templateFunction.bind(null, _fetch)
: templateFunction;
};
const connectToReporter = (templateFunction, isErrorReporter = false) => {
return typeof templateFunction === 'function'
? templateFunction.bind(
null,
isErrorReporter ? setFetchError : setFetchData
)
: templateFunction;
};
const connectToFetcherAndReporter = templateFunction => {
return typeof templateFunction === 'function'
? connectToReporter(connectToFetcher(templateFunction), true)
: templateFunction;
};
return {
connectToFetcherAndReporter,
fetch:_fetch,
fetchData,
fetchError,
isLoading
};
};
export { useFetch };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment