Last active
December 13, 2021 17:08
-
-
Save jasonsbarr/84c39c83070ced72ad11b69661fdfbed to your computer and use it in GitHub Desktop.
React hook to render data from a GET request using `fetch` based on states of a Promise lifecycle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useFetchGet } from "../hooks"; | |
| import ResolvedComponent from "./"; | |
| /** | |
| * Example use case | |
| * @see [Use in an actual project]{@link https://github.com/jasonsbarr/Sprint-Challenge-Single-Page-Apps/blob/d379e83f5d2bb77566d5fd37bbf2d5812438417d/src/pages/Characters.js|Github} | |
| */ | |
| const Component = () => { | |
| const render = useFetchGet(url); | |
| return render({ | |
| initial: () => <div>Haven't fetched yet!</div> | |
| pending: () => <div>Loading...</div>, | |
| error: err => <div>Error: {err.message}</div>, | |
| data: data => <ResolvedComponent data={data} />, | |
| }); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Matches current state of a Promise lifecycle and returns | |
| * Object of partially applied functions to render data. | |
| * | |
| * @param {Object} state | |
| * @param {Object} match | |
| * @returns {Object} | |
| */ | |
| const matchAsyncStates = state => match => | |
| state.initial ? match.initial() | |
| : state.pending ? match.pending() | |
| : state.error ? match.error(state.error) | |
| : state.data ? match.data(state.data) | |
| : null; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState, useEffect } from "react"; | |
| import { matchAsyncStates as render } from "./utils"; | |
| /** | |
| * React hook for conditional rendering based on Promise life- | |
| * cycle states for simple GET operations using fetch(). | |
| * | |
| * @param {String} url - The URL to run the query on | |
| * @param {Object} args - Set of args passed to function | |
| * @param {Boolean} [args.initialPersist=false] - whether initial state should be rendered while Promise is pending | |
| * @param {String} [args.method="json"] - response object method | |
| * @returns {Function} | |
| */ | |
| export const useFetchGet = ( | |
| url, | |
| { initialPersist = false, method = "json" } = {}, | |
| ) => { | |
| const [initial, setInitial] = useState(true); | |
| const [pending, setPending] = useState(false); | |
| const [data, setData] = useState(null); | |
| const [error, setError] = useState(null); | |
| useEffect(() => { | |
| setInitial(initialPersist); | |
| setPending(true); | |
| fetch(url) | |
| .then(response => { | |
| return !response.ok | |
| ? new Error(response.statusText) | |
| : response; | |
| }) | |
| .then(response => response[method]()) | |
| .then(data => { | |
| setInitial(false); | |
| setPending(false); | |
| setError(null); | |
| setData(data); | |
| }) | |
| .catch(error => { | |
| setInitial(false); | |
| setPending(false); | |
| setError(error); | |
| setData(null); | |
| }); | |
| }, [initialPersist, method, url]); | |
| return render({ initial, pending, error, data }); | |
| }; | |
| export default useFetchGet; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment