Created
June 7, 2019 22:55
-
-
Save crobinson42/63618ff183e56c33c1e1e80797f8ed3b to your computer and use it in GitHub Desktop.
JS-data React HOC
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
/* eslint-disable react/no-multi-comp, react/prop-types */ | |
import React from 'react' | |
import hoistNonReactStatic from 'hoist-non-react-statics' | |
import shallowEqual from '../utils/shallowEqual' | |
function ConnectModelsHOC({ loadingProp, modelName, modelNames }, mapPropsWithModels) { | |
return WrappedComponent => { | |
class ConnectModels extends React.Component { | |
static contextType = '' | |
constructor(props) { | |
super(props) | |
this.state = { | |
propsToPass: {}, | |
} | |
if (Array.isArray(modelNames)) { | |
this.models = modelNames.map(name => store[name]) | |
this.modelsByName = modelNames.reduce((acc, name) => { | |
acc[name] = store[name] | |
return acc | |
}, {}) | |
} else if (modelName) { | |
this.models = [store[modelName]] | |
} else { | |
this.models = [] | |
} | |
this.promise = undefined | |
this.computeProps() | |
} | |
componentDidMount() { | |
this.models.forEach(model => model.on('change', this.computeProps)) | |
} | |
componentDidUpdate(prevProps) { | |
if (!shallowEqual(prevProps, this.props)) this.computeProps() | |
} | |
componentWillUnmount() { | |
this.models.forEach(model => model.off('change', this.computeProps)) | |
} | |
computeProps = () => { | |
if (this.promise) return | |
const mapPropsWithModelsValue = mapPropsWithModels( | |
this.modelsByName || this.models[0], | |
this.props, | |
) | |
if (mapPropsWithModelsValue && mapPropsWithModelsValue.then) | |
this.promise = mapPropsWithModelsValue | |
if (this.promise) { | |
this.promise.then(propsToPass => { | |
this.promise = undefined | |
this.setState({ | |
propsToPass, | |
}) | |
}) | |
} else if (mapPropsWithModelsValue) { | |
this.setState({ | |
propsToPass: mapPropsWithModelsValue, | |
}) | |
} | |
} | |
render() { | |
const newObj = {} | |
if (loadingProp) newObj[loadingProp] = Boolean(this.promise) | |
const props = Object.assign(newObj, this.props, this.state.propsToPass) | |
return <WrappedComponent ref={this.props.forwardedRef} {...props} /> | |
} | |
} | |
ConnectModels.displayName = `ConnectModels(${WrappedComponent.displayName || | |
WrappedComponent.name || | |
'Component'})` | |
hoistNonReactStatic(ConnectModels, WrappedComponent) | |
return React.forwardRef((props, ref) => <ConnectModels forwardedRef={ref} {...props} />) | |
} | |
} | |
export default ConnectModelsHOC |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment