Skip to content

Instantly share code, notes, and snippets.

@itsMapleLeaf
Created March 13, 2018 22:41
Show Gist options
  • Select an option

  • Save itsMapleLeaf/bf658c254d7c167d1de147695584adf6 to your computer and use it in GitHub Desktop.

Select an option

Save itsMapleLeaf/bf658c254d7c167d1de147695584adf6 to your computer and use it in GitHub Desktop.
<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}`}
}
}}
/>
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