Skip to content

Instantly share code, notes, and snippets.

@tgriesser
Last active December 21, 2015 16:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tgriesser/d5d80ade6f895c28e659 to your computer and use it in GitHub Desktop.
Save tgriesser/d5d80ade6f895c28e659 to your computer and use it in GitHub Desktop.
import {Component} from 'react'
import shallowEqual from 'react/lib/shallowEqual'
export function observe(ComposedComponent) {
if (!ComposedComponent.observe) {
return ComposedComponent
}
Object.defineProperty(ComposedComponent.prototype, 'data', {
get: function() {
return this.props.data
}
})
const Enhancer = class extends Component {
constructor(props, context) {
super(props, context)
this.subscriptions = {}
this.state = {}
this.resubscribe(props, context)
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
return (
!shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState) ||
!shallowEqual(this.context, nextContext)
)
}
componentWillReceiveProps(props, context) {
this.resubscribe(props, context)
}
componentWillUnmount() {
this.unsubscribe()
}
resubscribe(props, context) {
const newObservables = ComposedComponent.observe(props, context)
const newSubscriptions = {}
Object.keys(newObservables).forEach((key) => {
let value = newObservables[key]
if (typeof value.subscribe !== 'function') {
throw new Error(`Must observe observables, ${key} is not observable`)
}
newSubscriptions[key] = value.subscribe({
next: (val) => {
if (this.state.hasOwnProperty(key)) {
this.setState({[key]: val})
} else {
this.state[key] = val
}
},
throw: () => {},
return: () => {}
})
if (!this.state.hasOwnProperty(key)) {
this.state[key] = null
}
})
this.unsubscribe()
this.subscriptions = newSubscriptions
}
unsubscribe() {
for (let key in this.subscriptions) {
if (this.subscriptions.hasOwnProperty(key)) {
this.subscriptions[key].unsubscribe()
}
}
this.subscriptions = {}
}
render() {
return <ComposedComponent {...this.props} data={this.state} />
}
}
Enhancer.propTypes = ComposedComponent.propTypes
Enhancer.contextTypes = ComposedComponent.contextTypes
return Enhancer
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment