Created
August 19, 2015 07:42
-
-
Save JorgenEvens/a9269c0866b554bdb5a0 to your computer and use it in GitHub Desktop.
A React composite component that loads properties for us and prevents re-rendering until it changes.
This file contains 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
import _ from 'lodash'; | |
import React from 'react'; | |
const debug = false; | |
const log = debug ? console.log.bind(console) : () => {}; | |
const getPath = ( obj, path, defaultValue ) => { | |
_.each( path.split('.'), function( key ) { | |
if( _.isUndefined( obj ) ) | |
return false; | |
if( obj === null ) | |
return false; | |
if( _.isFunction( obj[key] ) ) | |
obj = obj[key](); | |
else | |
obj = obj[key]; | |
}); | |
if( _.isUndefined( obj ) ) | |
return defaultValue; | |
return obj; | |
}; | |
export default function Aware( options, Component, propKey, overwriteOptions = null ) { | |
options = _.merge({ | |
storeMethod: 'get', | |
actionMethod: 'get', | |
isInteger: true | |
}, options, overwriteOptions ); | |
const { | |
property, | |
store, storeMethod, | |
actions, actionMethod, | |
isInteger | |
} = options; | |
const getId = ( obj ) => { | |
var id = getPath(obj.props, propKey) || getPath(obj, propKey); | |
if( _.isFunction( id ) ) | |
id = id.call(obj); | |
if( isInteger ) | |
return parseInt( id, 10 ) || false; | |
return id || false; | |
}; | |
var contextTypes = {}; | |
if( propKey.indexOf( 'context.' ) == 0 ) | |
contextTypes = { [propKey.split('.')[1] ]: React.PropTypes.any }; | |
return class extends React.Component { | |
static contextTypes = contextTypes; | |
constructor() { | |
super(); | |
this.state = { entity: null }; | |
} | |
request( id ) { | |
log(`request[${property}] `, id); | |
if( _.isFunction( actionMethod ) ) | |
return actionMethod( id ); | |
return actions[actionMethod]( id ); | |
} | |
get( id ) { | |
log(`get[${property}] `, id); | |
if( _.isFunction( storeMethod ) ) | |
return storeMethod( id ); | |
return store[storeMethod]( id ); | |
} | |
ready() { | |
return !!this.state.entity; | |
} | |
_update = () => { | |
this.setState({ | |
entity: this.get( getId(this) ) | |
}); | |
} | |
componentWillMount() { | |
const entityId = getId( this ); | |
log(`component will mount[${property}]`, entityId, entityId !== false); | |
if( entityId !== false ) | |
this.request( entityId ); | |
} | |
componentWillReceiveProps( props, state ) { | |
const nextId = getId({ | |
props, | |
state, | |
context: this.context | |
}); | |
const shouldRequest = !this.ready() || | |
(nextId !== false && getId( this ) != nextId); | |
log(`will receive props[${property}]`, nextId, shouldRequest, this); | |
if( shouldRequest ) | |
this.request(nextId); | |
} | |
componentDidMount() { | |
store.addChangeListener(this._update); | |
} | |
componentWillUnmount() { | |
store.removeChangeListener(this._update); | |
} | |
shouldComponentUpdate( props, state ) { | |
log(`shouldComponentUpdate[${property}] `, !!state.entity); | |
return !!state.entity; | |
} | |
render() { | |
const props = { | |
...this.props, | |
[property]: this.state.entity | |
}; | |
log(`props[${property}]`, props); | |
return <Component {...props} />; | |
} | |
}; | |
} |
This file contains 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
"use strict"; | |
import _ from 'lodash'; | |
import { User as UserStore } from 'stores'; | |
import { User as UserActions } from 'actions'; | |
import { BaseAware } from 'composite'; | |
const aware = _.partial( BaseAware, { | |
property: 'user', | |
store: UserStore, | |
actions: UserActions | |
}); | |
export default aware; | |
export function ensure(...args) { | |
return function( classDefinition ) { | |
return aware( classDefinition, ...args ); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment