Created
February 2, 2020 22:03
-
-
Save jcuffe/882de6d48d9e419c85787c843672edab to your computer and use it in GitHub Desktop.
Suspense integration for HelloRevel Redux
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
const App = () => ( | |
<ErrorBoundary> | |
<Suspense fallback={LoadingPage}> | |
// ...routes | |
</Suspense> | |
</ErrorBoundary> | |
) |
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
const Detail = () => { | |
const { id } = useMatch() | |
const event = useResource("events", id, fetchEvent) | |
return ( | |
// `event` is guaranteed to be defined here | |
) | |
} |
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
export const fetcher = (key, dispatch) => { | |
const config = { | |
... | |
} | |
// Make the request | |
const promise = axios(config) | |
.then(data => dispatch(updateReducer(data)) | |
.catch(err => dispatch(updateReducer(err)) | |
// Store the promise on state for the fetcher | |
dispatch(updateReducer(promise)) | |
} |
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
export const useResource(name, key, fetcher, fetcherArgs) { | |
// Look for value on top level reducer | |
const value = useSelector(state => state[name][key]) | |
const dispatch = useDispatch() | |
switch(getState(value)) { | |
// If the value on state is a promise, we're waiting for a fetch | |
// Throw the promise for Suspense | |
case PENDING: | |
// If the value is an error, our fetch failed | |
// Throw an error for the ErrorBoundary | |
case FAILURE: | |
throw value | |
// We have our data! | |
case SUCCESS: | |
return value | |
// This is the first access attempt (or something cleared the value) | |
// Kick off a fetch | |
default: | |
fetcher(key, ...fetcherArgs, dispatch) | |
} | |
} | |
getState(value) { | |
const states = { | |
PENDING: isPromise, | |
FAILURE: isError, | |
SUCCESS: isValue | |
} | |
for (let key in states) { | |
if (states[key](value)) { | |
return states[key] | |
} | |
} | |
} | |
isValue = value => !isPromise(value) && isDefined(value) && !isError(value) | |
isPromise = value => value && typeof value.then == "function" | |
isUndefined = value => value === undefined | |
isError = value => value instanceof Error |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment