Created
March 13, 2018 22:41
-
-
Save itsMapleLeaf/bf658c254d7c167d1de147695584adf6 to your computer and use it in GitHub Desktop.
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
| <Fetcher | |
| fetch={() => getBlogPost(props.id)} | |
| render={state => { | |
| switch (state.state) { | |
| case 'idle': | |
| case 'fetching': | |
| case 'fetching-long': | |
| return <LoadingScreen message="Fetching blog post..." /> | |
| case 'success': | |
| return <BlogPost postData={state.data} /> | |
| case 'error': | |
| return <FetchError message={`Error fetching post "${props.id}": ${state.error}`} | |
| } | |
| }} | |
| /> |
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 { action, observable } from "mobx" | |
| import { observer } from "mobx-react" | |
| import * as React from "react" | |
| export type FetcherProps<T> = { | |
| longWaitTimeout?: number | |
| fetch: () => Promise<T> | |
| render: (fetchState: FetchState<T>) => React.ReactNode | |
| } | |
| export type FetchState<T> = | |
| // component hasn't mounted yet, nothing is happening | |
| | { state: "idle" } | |
| // currently fetching the data | |
| | { state: "fetching" } | |
| // fetching the data, though it's taken a while | |
| | { state: "fetching-long" } | |
| // received data | |
| | { state: "success"; data: T } | |
| // error fetching data | |
| | { state: "error"; error: any } | |
| @observer | |
| export class Fetcher<T> extends React.Component<FetcherProps<T>> { | |
| @observable fetchState: FetchState<T> = { state: "idle" } | |
| @action | |
| setFetchState(fetchState: FetchState<T>) { | |
| this.fetchState = fetchState | |
| } | |
| async doFetch() { | |
| this.setFetchState({ state: "fetching" }) | |
| setTimeout(() => { | |
| if (this.fetchState.state === "fetching") { | |
| this.setFetchState({ state: "fetching-long" }) | |
| } | |
| }, this.props.longWaitTimeout || 2500) | |
| try { | |
| const data = await this.props.fetch() | |
| this.setFetchState({ state: "success", data }) | |
| } catch (error) { | |
| this.setFetchState({ state: "error", error }) | |
| } | |
| } | |
| componentDidMount() { | |
| // tslint:disable-next-line | |
| this.doFetch() | |
| } | |
| render() { | |
| return this.props.render(this.fetchState) | |
| } | |
| } | |
| export function createFetcher<T>() { | |
| return Fetcher as new () => Fetcher<T> | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment