diff --git a/docs/api.md b/docs/api.md
index 9690621..098b4c9 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -58,7 +58,7 @@ class App extends React.Component {
`connect` accept a single object with these properties:
- `actions` (*Object*): map component properties to refraction publishers. Attributes name of `actions` identify component properties, attributes value identify refraction publishers. If a publisher with that name is unavailable, connect will create a new function that publish the value for you.
-- `subscriptions` (*Object*): an object that consist in a series of function that return new properties. Attributes name of `subscriptions` identify channels to handle, attributes value identify a function that must return an object representing new component props. This function accept the value hold by the channel and the actual props of component. **New properties will be merged with the old. Returning an object that has no value for a certain prop means maintain the old one.**
+- `subscriptions` (*Object*): an object that consist in a series of function that return new properties. Attributes name of `subscriptions` identify channels to handle, attributes value identify a function that must return an object representing new component props or a Promise that resolve with them. This function accept the value hold by the channel and the actual props of component. **New properties will be merged with the old. Returning an object that has no value for a certain prop means maintain the old one.**
#### Returns
diff --git a/package.json b/package.json
index 1b90cdb..ca89fcc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "refraction-react",
- "version": "1.0.3",
+ "version": "1.1.0",
"description": "React bindings for Refraction",
"main": "lib/index.js",
"files": [
@@ -88,4 +88,4 @@
"loose-envify"
]
}
-}
+}
\ No newline at end of file
diff --git a/src/RefractionConnector.js b/src/RefractionConnector.js
index 3a1c19b..5817515 100644
--- a/src/RefractionConnector.js
+++ b/src/RefractionConnector.js
@@ -1,7 +1,6 @@
import React from 'react';
export default class RefractionConnector extends React.Component {
-
static propTypes = {
actions: React.PropTypes.object,
subscriptions: React.PropTypes.object,
@@ -9,39 +8,44 @@ export default class RefractionConnector extends React.Component {
React.PropTypes.func,
React.PropTypes.string,
]).isRequired,
- }
+ };
static contextTypes = {
refraction: React.PropTypes.object.isRequired,
- }
+ };
static defaultProps = {
actions: {},
subscriptions: {},
Component: 'div',
- }
+ };
constructor(props, context) {
super(props, context);
- Object.keys(props.subscriptions).forEach((key) => {
- this[key] = (param) => {
- this.setState(
- Object.assign(
- {},
- this.state,
- props.subscriptions[key](param, Object.assign({}, this.refs.element.props))
- )
+ Object.keys(props.subscriptions).forEach(key => {
+ this[key] = param => {
+ const newProps = props.subscriptions[key](
+ param,
+ Object.assign({}, this.refs.element.props)
);
+ if (newProps && typeof newProps.then === 'function') {
+ newProps.then(this.mergeState);
+ } else {
+ this.mergeState(newProps);
+ }
};
});
this.alias = {};
- Object.keys(props.actions).forEach((key) => {
+ Object.keys(props.actions).forEach(key => {
const { refraction } = this.context;
if (refraction[props.actions[key]]) {
this.alias[key] = refraction[props.actions[key]].bind(refraction);
} else {
- this.alias[key] = refraction.publish.bind(refraction, props.actions[key]);
+ this.alias[key] = refraction.publish.bind(
+ refraction,
+ props.actions[key]
+ );
}
});
@@ -53,11 +57,17 @@ export default class RefractionConnector extends React.Component {
this.context.refraction.unsubscribe(this);
}
+ mergeState = obj => {
+ this.setState(Object.assign({}, this.state, obj));
+ };
+
render() {
const props = Object.assign({}, this.props);
delete props.actions;
delete props.subscriptions;
const { Component, ...others } = props;
- return ;
+ return (
+
+ );
}
}
diff --git a/test/RefractionConnector.spec.js b/test/RefractionConnector.spec.js
index b31b2f5..1405ac9 100644
--- a/test/RefractionConnector.spec.js
+++ b/test/RefractionConnector.spec.js
@@ -6,15 +6,22 @@ import { Provider } from '../src/';
import { Child, configs } from './common';
import RefractionConnector from '../src/RefractionConnector';
-describe('RefractionConnector', () => {
+const wait = () =>
+ new Promise(resolve => {
+ setTimeout(resolve, 500);
+ });
+
+describe('RefractionConnector', function testRefractionConnector() {
+ this.timeout(5000);
+
class CustomRefraction extends Refraction {
- onInputChange = (e) => {
+ onInputChange = e => {
this.publish('onInputChange', e.target.value);
- }
+ };
}
let refraction = new CustomRefraction();
- const testConnector = (actions, subscriptions) => {
+ const testConnector = (actions, subscriptions, done) => {
const rendered = TestUtils.renderIntoDocument(
{
/>
);
- const connector = TestUtils.findRenderedComponentWithType(rendered, RefractionConnector);
+ const connector = TestUtils.findRenderedComponentWithType(
+ rendered,
+ RefractionConnector
+ );
expect(connector.props).toEqual({
actions,
subscriptions,
@@ -47,14 +57,21 @@ describe('RefractionConnector', () => {
const input = TestUtils.findRenderedDOMComponentWithTag(rendered, 'input');
TestUtils.Simulate.change(input, { target: { value: 'test1' } });
- expect(connector.state).toEqual({ value: 'test1' });
- expect(connected.props.value).toEqual('test1');
- TestUtils.Simulate.change(input, { target: { value: 'test2' } });
- expect(connector.state).toEqual({ value: 'test1test2' });
- expect(connected.props.value).toEqual('test1test2');
+ wait()
+ .then(() => {
+ expect(connector.state).toEqual({ value: 'test1' });
+ expect(connected.props.value).toEqual('test1');
+ TestUtils.Simulate.change(input, { target: { value: 'test2' } });
+ return wait();
+ })
+ .then(() => {
+ expect(connector.state).toEqual({ value: 'test1test2' });
+ expect(connected.props.value).toEqual('test1test2');
- connector.componentWillUnmount();
- expect(refraction.mediator.subscribers.indexOf(connector)).toEqual(-1);
+ connector.componentWillUnmount();
+ expect(refraction.mediator.subscribers.indexOf(connector)).toEqual(-1);
+ if (done) done();
+ });
};
afterEach(() => {
@@ -73,4 +90,20 @@ describe('RefractionConnector', () => {
}),
});
});
+
+ it('should handle Promises in subscriptions', done => {
+ refraction = new Refraction();
+ testConnector(
+ configs.actions,
+ {
+ onInputChange: (e, props) =>
+ Promise.resolve({
+ value: e.target.value
+ ? props.value + e.target.value
+ : e.target.value,
+ }),
+ },
+ done
+ );
+ });
});