Last active
June 13, 2018 20:34
-
-
Save killtheliterate/b45776ab122c5be16a236d3b48154355 to your computer and use it in GitHub Desktop.
A HOC for fetching data
This file contains 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
// @see: https://gist.github.com/bvaughn/982ab689a41097237f6e9860db7ca8d6 | |
import * as React from 'react' | |
// --------------------------------------------------------------------------- | |
export type EffOptions = { | |
StateComponent?: React.ComponentType<any> | |
} | |
export type EffProps = { | |
effect: () => Promise<any> | |
onError: (err: Error) => void | |
shouldEffectKey: string | |
} | |
export type EffState = { | |
isResolved: boolean | |
prevKey?: string | |
} | |
export function withEffect ({ StateComponent }: EffOptions) { | |
return function <P> (CC: React.ComponentType<P>) { | |
const IsEff: React.SFC<{}> = () => StateComponent | |
? (<StateComponent />) | |
: (<div>...loading</div>) | |
return class Eff extends React.Component<P & EffProps, EffState> { | |
_resolvingKey: string | void = undefined | |
state = { | |
isResolved: false, | |
prevKey: undefined | |
} | |
static getDerivedStateFromProps (nextProps: P & EffProps, prevState: EffState) { | |
if (nextProps.shouldEffectKey !== prevState.prevKey) { | |
return { | |
isResolved: false, | |
prevKey: nextProps.shouldEffectKey | |
} | |
} | |
return null | |
} | |
componentDidMount () { | |
this._effect(this.props.shouldEffectKey) | |
} | |
componentWillUnmount () { | |
this._resolvingKey = undefined | |
} | |
componentDidUpdate () { | |
if (this.state.isResolved === false) { | |
this._effect(this.props.shouldEffectKey) | |
} | |
} | |
render () { | |
const { effect, shouldEffectKey, onError, ...restProps } = this.props as EffProps | |
return this.state.isResolved | |
? (<CC {...restProps}/>) | |
: (<IsEff />) | |
} | |
// --------------------------------------------------------------------- | |
_effect = (key: EffProps['shouldEffectKey']) => { | |
if (key === this._resolvingKey) { | |
return // already resolving | |
} | |
this._resolvingKey = key | |
this.props.effect() | |
.then( | |
() => { | |
if (key === this._resolvingKey) { | |
this.setState(() => ({ isResolved: true })) | |
} | |
}, | |
(err: Error) => { | |
if (key === this._resolvingKey) { | |
this.setState(() => ({ isResolved: true })) | |
this.props.onError(err) | |
} | |
} | |
) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment