Skip to content

Instantly share code, notes, and snippets.

@srph
Created January 26, 2018 21:20
Show Gist options
  • Save srph/019e1bfe9a111108e09f29352663484e to your computer and use it in GitHub Desktop.
Save srph/019e1bfe9a111108e09f29352663484e to your computer and use it in GitHub Desktop.
React: Declaratively resolve data

Usage

<Resolver promise={() => axios.get('data')}>
  {(data) => {
    return <div>{data.name}</div>
  })}
</Resolver>
import React, {Children, cloneElement} from 'react'
import T from 'prop-types'
/**
* Delay component from mounting until promise is resolved.
*/
class Resolver extends React.Component {
state = {
resolved: false,
data: null
}
componentDidMount() {
this.resolve(this.props)
}
componentWillReceiveProps(nextProps) {
if (this.shouldRun(nextProps)) {
this.resolve(nextProps)
}
}
render() {
if (!this.state.resolved) {
return <div />
}
if (this.props.key) {
return this.props.children({
...this.getProps(),
[key]: this.state.data
})
}
return Children.map(this.props.children, child => {
return cloneElement(child, this.getProps())
})
}
resolve(props = this.props) {
Promise.resolve(props.promise())
.then(data => {
this.setState({
resolved: true,
data
})
})
}
shouldRun(props = this.props) {
if (typeof props.shouldRun === 'boolean') {
return props.shouldRun
}
return props.shouldRun(props)
}
getProps(props = this.props) {
const {key, promise, shouldRun, children, ...waterfall} = props
return waterfall
}
}
Resolver.propTypes = {
shouldRun: T.oneOfType([T.bool, T.func])
}
Resolver.defaultProps = {
shouldRun: false
}
Resolver.resolver = function(key, promise, shouldRun) {
// resolver(promise, shouldRun)
if (promise == null) {
shouldRun = promise
promise = key
key = null
}
return Component => {
return class extends React.Component {
render() {
<Resolver key={key}
promise={promise}
shouldRun={shouldRun}
{...this.props} />
}
}
}
}
export default Resolver
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment