Skip to content

Instantly share code, notes, and snippets.

@amireh
Created April 23, 2015 18:12
Show Gist options
  • Save amireh/74b2e66c69afabd93a08 to your computer and use it in GitHub Desktop.
Save amireh/74b2e66c69afabd93a08 to your computer and use it in GitHub Desktop.
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