Skip to content

Instantly share code, notes, and snippets.

@fdecampredon
Last active September 15, 2016 09:26
Show Gist options
  • Save fdecampredon/493a234ab283a201b6af to your computer and use it in GitHub Desktop.
Save fdecampredon/493a234ab283a201b6af to your computer and use it in GitHub Desktop.
'use strict';
var Rx = require('rx');
var React = require('react');
var React = require('react');
var Component = require('./Component');
var utils = require('./utils');
var inherits = utils.inherits;
var isObservable = utils.isObservable;
var flatten = utils.flatten;
function mapChildren(children, mapFunc) {
if (!Array.isArray(children)) {
return [mapFunc(children)];
} else {
return flatten(children).map(mapFunc);
}
}
function elementToObservable(element) {
if (isObservable(element) && !typeof element === 'function') {
return element.flatMapLatest(elementToObservable);
}
var observableProps;
var children;
if (React.isValidElement(element)) {
var props = element.props;
for (var prop in props) {
if (props.hasOwnProperty(prop)) {
if (prop !== 'children') {
var value = elementToObservable(props[prop]);
if (isObservable(value) && !typeof value === 'function') {
if (!observableProps) {
observableProps = [];
}
observableProps.push(
value.map(function (value) {
return {
prop: prop,
value: value
};
})
);
}
} else {
children = mapChildren(props.children, elementToObservable);
}
}
}
}
var hasObservableChild = (children && children.some(isObservable));
if (observableProps || hasObservableChild) {
var propsObservable = (
observableProps ?
Rx.Observable.combineLatest(observableProps, function () {
return React.cloneElement(
element,
[].reduce.call(arguments, function (props, descr) {
props[descr.props] = props.value;
}, {})
);
}) :
Rx.Observable.of(null)
);
var childrenObservable = (
hasObservableChild ?
Rx.Observable.combineLatest(
children.map(function (child) {
return isObservable(child) ? child : Rx.Observable.of(child);
}),
function () {
return [].slice.call(arguments);
}
) :
Rx.Observable.of(children)
);
return Rx.Observable.combineLatest(
propsObservable, childrenObservable,
function (props, children) {
return React.cloneElement.apply(null, [element, props].concat(children));
}
);
}
return element;
}
function createRxComponent(factory) {
function RxComponent(props, context) {
Component.call(this, props, context);
}
RxComponent.displayName = factory;
inherits(RxComponent, Component, {
componentWillMount: function () {
var observable = elementToObservable(factory(this.propsStream));
if (isObservable(observable)) {
this.getStateStream = function () {
return observable.map(function (element) {
return {
_renderedElement: element
};
});
};
} else {
this.setState({_renderedElement: observable});
}
Component.prototype.componentWillMount.call(this);
},
render: function () {
return this.state && this.state._renderedElement;
}
});
return RxComponent;
}
module.exports = createRxComponent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment