Created
April 23, 2015 18:12
-
-
Save amireh/74b2e66c69afabd93a08 to your computer and use it in GitHub Desktop.
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
const assign = require('utils/assign'); | |
/** | |
* @private | |
* | |
* Attach a "mutator" to a component's `props` object, allowing setting of | |
* dynamic properties that will persist through the component's lifecycle hooks. | |
* | |
* This is useful if you want to achieve the effect of calling #setProps() | |
* directly on an element even though you might not be able to if it's not the | |
* root element. | |
* | |
* Needless to say, this is absolutely an anti-pattern in React, but maybe not | |
* so much for the needs of this haxors. :) | |
* | |
* @param {React.Element} owner | |
* The mounted instance of a React component to mutate. | |
* | |
* @example | |
* | |
* componentWillMount() { | |
* this.mutableProps = new MutableProps(this); | |
* this.mutableProps.set('foo', 'bar'); | |
* }, | |
* | |
* render() { | |
* return <div>{this.props.foo}</div>; // <div>bar</div> | |
* } | |
*/ | |
function MutableProps(owner) { | |
// @property {Object} compositeProps | |
// | |
// This will point to the computed set of both original and dynamic props | |
// which we'll yield whenever `this.props` is referenced. | |
var compositeProps = owner.props; | |
// @property {Object} originalProps | |
// @immutable | |
// | |
// This will always point to whatever the component has originally received | |
// as props (e.g. when mounted, when updated with #setProps(), or when React | |
// updates a child element inside its render tree.) | |
var originalProps = owner.props; | |
// @property {Object} dynamicProps | |
// | |
// The "dynamic", or internal, props to compose along with the original ones. | |
var dynamicProps = {}; | |
function compose() { | |
compositeProps = assign({}, originalProps, dynamicProps); | |
} | |
function setDynamicProp(propName, value) { | |
dynamicProps[propName] = value; | |
compose(); | |
} | |
// "Virgin" Object.hasOwnProperty(); ignores dynamic props and instead looks | |
// up only the original ones. | |
function hasOriginalProp(propName) { | |
return ( | |
originalProps.hasOwnProperty(propName) && | |
!dynamicProps.hasOwnProperty(propName) | |
); | |
} | |
Object.defineProperty(owner, 'props', { | |
get: function() { return compositeProps; }, | |
set: function(newOriginalProps) { | |
originalProps = newOriginalProps; | |
compose(); | |
} | |
}); | |
return { | |
set: setDynamicProp, | |
hasOwnProperty: hasOriginalProp | |
}; | |
} | |
module.exports = MutableProps; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment