Skip to content

Instantly share code, notes, and snippets.

@goatslacker
Last active October 1, 2015 00:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save goatslacker/5f84bf1793cbc7badda3 to your computer and use it in GitHub Desktop.
Save goatslacker/5f84bf1793cbc7badda3 to your computer and use it in GitHub Desktop.
The new alt connect?
class InfoView extends React.Component {
render() {
return <div>{this.props.things}</div>
}
}
export default connect({
listenTo() {
return [InfoStore]
},
getProps(props, context) {
return {
things: InfoStore.fetchInfo(),
}
}
}, InfoView)
import React, { PropTypes } from 'react'
import { Resolver } from 'react-resolver'
import isPromise from 'is-promise'
function connect(spec, Component) {
return React.createClass({
displayName: `Stateful${Component.displayName || Component.name}Container`,
contextTypes: {
flux: React.PropTypes.object
},
getInitialState() {
this.flux = this.context.flux
this.stores = this.flux ? this.flux.stores : {}
this.spec = typeof spec === 'function'
? spec(this.stores, this.flux)
: spec
return this.getNextState()
},
componentWillMount() {
if (this.spec.willMount) this.call(this.spec.willMount)
},
componentDidMount() {
const stores = this.spec.listenTo ? this.call(this.spec.listenTo) : []
this.storeListeners = stores.map((store) => {
return store.listen(() => this.setState(this.getNextState()))
})
if (this.spec.didMount) this.call(this.spec.didMount)
},
componentWillUnmount() {
this.storeListeners.forEach(unlisten => unlisten())
if (this.spec.willUnmount) this.call(this.spec.willUnmount)
},
componentWillReceiveProps(nextProps) {
if (this.spec.willReceiveProps) this.call(this.spec.willReceiveProps)
this.setState(this.getNextState(nextProps))
},
shouldComponentUpdate(nextProps) {
return this.spec.shouldComponentUpdate
? this.call(this.spec.shouldComponentUpdate)
: true
},
call(f, props = this.props) {
return f(props, this.context, this.flux)
},
getNextState(nextProps = this.props) {
const reduced = this.spec.getProps
? this.call(this.spec.getProps, nextProps)
: nextProps
const {
props,
resolve,
} = Object.keys(reduced).reduce((obj, key) => {
const prop = reduced[key]
if (isPromise(prop)) {
obj.resolve[key] = () => prop
} else {
obj.props[key] = prop
}
return obj
}, {
props: {},
resolve: {},
})
return { props, resolve }
},
render() {
return (
<Resolver props={this.state.props} resolve={this.state.resolve}>
{resolved => {
return <Component {...resolved} flux={this.flux} />
}}
</Resolver>
)
},
})
}
export default connect
@goatslacker
Copy link
Author

cc @taion @lelandrichardson @cpsubrian

A couple of comments about this new connect.js which is meant to replace connectToStores.

  1. the enhance() method is a way to hook into connectToStores so you can inject all kinds of other props, not sure this method should exist but I do have a couple of use cases for it. If it does exist the enhance name is awful, what's a better one?
  2. Should reduceProps always fire after resolveProps and include the resolveProps in there in case you want to transform them? Currently you can reduceProps and resolveProps. resolveProps is the async version and reduceProps is for anything local. Is this too confusing?
  3. There are a few things missing, I want to add lifecycle hooks for willMount, willUnmount, shouldComponentUpdate, etc...
  4. What do we do about the whole statics not being copied over? My guess is we provide a statics where you can provide your on static methods on there which will be placed on the container class (this is useful for react-router among other things)

@goatslacker
Copy link
Author

cc @ericclemmons this uses react-resolver to resolve the async props. I still have yet to make this work universally but that's the next step. Hopefully I can get rid of Render then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment