Skip to content

Instantly share code, notes, and snippets.

@rattrayalex
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rattrayalex/cb5551618df6d77417c3 to your computer and use it in GitHub Desktop.
Save rattrayalex/cb5551618df6d77417c3 to your computer and use it in GitHub Desktop.
Nuclearjs React DataProvider component
import React from "react"
import Reactor from "./reactor"
function _toJS(x) {
if (x && x.toJS && typeof x.toJS === 'function') {
return x.toJS()
}
return x
}
export default React.createClass({
propTypes: {
reactor: React.PropTypes.instanceOf(Reactor),
children: React.PropTypes.element.isRequired,
},
getInitialState() {
let state = {}
this.getDataBinding().forEach( (key, getter) =>
state[key] = _toJS(this.props.reactor.evaluate(getter))
)
return state
},
componentDidMount() {
this.__unwatchFns = []
this.getDataBinding().forEach( (key, getter) => {
let unwatchFn = this.props.reactor.observe(getter, (val) => {
let newState = {}
newState[key] = _toJS(val)
this.setState(newState)
})
this.__unwatchFns.push(unwatchFn)
})
},
componentWillUnmount() {
while (this.__unwatchFns.length) {
this.__unwatchFns.shift()()
}
},
getDataBinding() {
return Object.keys(this.props).filter( (key) =>
key !== 'reactor' && key !== 'children'
)
},
render() {
return React.withContext(
{ dispatch: this.props.reactor.dispatch },
React.cloneElement(this.props.children, this.state)
)
}
})
// Usage:
const reactor = new Reactor()
reactor.registerStores({
users: require('userStore'),
dogs: require('dogStore'),
})
const userGetter = [
['users'],
(users) => {
return users[0]
}
]
const dogGetter = [
['dogs'],
userGetter,
(dogs, user) => {
return dogs.findOne( (dog) => dog.owner === user )
}
]
const RootComponent = React.createClass({
render() {
return (
<DataProvider reactor={reactor} user={userGetter} dog={dogGetter}>
// gets `user` and `dog` props
<UserAndDogView />
</DataProvider>
)
}
})
const UserAndDogView = React.createClass({
propTypes: {
user: React.propTypes.object.isRequired,
dog: React.propTypes.object.isRequired,
},
_renameDog(e) {
let name = e.target.value
this.context.dispatch(RENAME_DOG, { name })
},
render() {
let { user, dog } = this.props
return (
<div>
<label>
{ user.name }
has a dog named:
<input
type="text"
value={ dog.name }
onChange={ this._renameDog }
/>
</label>
</div>
)
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment