From 3dc8eb8a648ac85a38b7662562377a9bb5848999 Mon Sep 17 00:00:00 2001 From: jeroenbreemhaar Date: Wed, 30 Aug 2017 14:07:47 +0200 Subject: [PATCH 1/4] trying to just target global, and if/elseing the need for renderToStaticMarkup --- package.json | 2 +- src/Resolver.js | 33 +++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index e5d52c0..8b6284c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "directories": { "test": "test" }, - "peerDependencies": { + "dependencies": { "react": "^0.14.6 || ^15.0.0-0", "react-dom": "^0.14.6 || ^15.0.0-0" }, diff --git a/src/Resolver.js b/src/Resolver.js index 0c1b62d..5e74e50 100644 --- a/src/Resolver.js +++ b/src/Resolver.js @@ -9,6 +9,17 @@ const CHILDREN = "ReactResolver.CHILDREN"; const HAS_RESOLVED = "ReactResolver.HAS_RESOLVED"; const IS_CLIENT = "ReactResolver.IS_CLIENT"; const PAYLOAD = "__REACT_RESOLVER_PAYLOAD__"; +const _global = this; // window or global + +/** + * Check if we're running under a ReactNative enviroment; + * @return {boolean} + * + * https://stackoverflow.com/questions/39468022/how-do-i-know-if-my-code-is-running-as-react-native + */ +function isReactNative() { + return (typeof navigator != 'undefined' && navigator.product == 'ReactNative'); +} export default class Resolver extends React.Component { static childContextTypes = { @@ -34,27 +45,29 @@ export default class Resolver extends React.Component { resolve: React.PropTypes.object, } - static render = function(render, node, data = window[PAYLOAD]) { + static render = function(render, node, data = _global[PAYLOAD]) { ReactDOM.render(( {render} ), node); - delete window[PAYLOAD]; + delete _global[PAYLOAD]; } static resolve = function(render, initialData = {}) { const queue = []; - renderToStaticMarkup( - { - queue.push(promise); - return Promise.resolve(true); - })}> - {render} - - ); + if (!isReactNative()) { + renderToStaticMarkup( + { + queue.push(promise); + return Promise.resolve(true); + })}> + {render} + + ); + } return Promise.all(queue).then((results) => { const data = { ...initialData }; From af2308d41aa3bad48394f86ff6f6ea761e3f934d Mon Sep 17 00:00:00 2001 From: jeroenbreemhaar Date: Wed, 30 Aug 2017 14:15:10 +0200 Subject: [PATCH 2/4] reset to peerDependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b6284c..e5d52c0 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "directories": { "test": "test" }, - "dependencies": { + "peerDependencies": { "react": "^0.14.6 || ^15.0.0-0", "react-dom": "^0.14.6 || ^15.0.0-0" }, From 052c526982c20dbbc39d1f0893a14742188d60fe Mon Sep 17 00:00:00 2001 From: jeroenbreemhaar Date: Wed, 30 Aug 2017 14:51:21 +0200 Subject: [PATCH 3/4] moving as close to current master as possible, so just commenting out deps for renderToStaticMarkup --- src/Resolver.js | 484 ++++++++++++++++++++++++------------------------ 1 file changed, 245 insertions(+), 239 deletions(-) diff --git a/src/Resolver.js b/src/Resolver.js index 5e74e50..0f8aad6 100644 --- a/src/Resolver.js +++ b/src/Resolver.js @@ -1,15 +1,20 @@ /* eslint-disable no-underscore-dangle */ import React from "react"; -import ReactDOM from "react-dom"; -import {renderToStaticMarkup} from "react-dom/server"; + +// react-dom seems to be clashing with react-native, no idea why +// so I'll just comment them out to make it work in react-native. +//import ReactDOM from "react-dom"; +//import {renderToStaticMarkup} from "react-dom/server"; + +let ReactDOM; +let renderToStaticMarkup const ID = "ReactResolver.ID"; const CHILDREN = "ReactResolver.CHILDREN"; const HAS_RESOLVED = "ReactResolver.HAS_RESOLVED"; const IS_CLIENT = "ReactResolver.IS_CLIENT"; const PAYLOAD = "__REACT_RESOLVER_PAYLOAD__"; -const _global = this; // window or global /** * Check if we're running under a ReactNative enviroment; @@ -21,294 +26,295 @@ function isReactNative() { return (typeof navigator != 'undefined' && navigator.product == 'ReactNative'); } + export default class Resolver extends React.Component { - static childContextTypes = { - resolver: React.PropTypes.instanceOf(Resolver), - } - - static contextTypes = { - resolver: React.PropTypes.instanceOf(Resolver), - } - - static defaultProps = { - data: {}, - props: {}, - resolve: {}, - } - - static displayName = "Resolver" - - static propTypes = { - children: React.PropTypes.func.isRequired, - data: React.PropTypes.object.isRequired, - props: React.PropTypes.object, - resolve: React.PropTypes.object, - } - - static render = function(render, node, data = _global[PAYLOAD]) { - ReactDOM.render(( - - {render} - - ), node); - - delete _global[PAYLOAD]; - } - - static resolve = function(render, initialData = {}) { - const queue = []; - - if (!isReactNative()) { - renderToStaticMarkup( - { - queue.push(promise); - return Promise.resolve(true); - })}> - {render} - - ); + static childContextTypes = { + resolver: React.PropTypes.instanceOf(Resolver), } - return Promise.all(queue).then((results) => { - const data = { ...initialData }; + static contextTypes = { + resolver: React.PropTypes.instanceOf(Resolver), + } - results.forEach(({ id, resolved }) => data[id] = resolved); + static defaultProps = { + data: {}, + props: {}, + resolve: {}, + } - if (Object.keys(initialData).length < Object.keys(data).length) { - return Resolver.resolve(render, data); - } + static displayName = "Resolver" - class Resolved extends React.Component { - static displayName = "Resolved" + static propTypes = { + children: React.PropTypes.func.isRequired, + data: React.PropTypes.object.isRequired, + props: React.PropTypes.object, + resolve: React.PropTypes.object, + } - render() { - return ( + static render = function(render, node, data = window[PAYLOAD]) { + ReactDOM.render(( - {render} + {render} - ); - } - } - - return { data, Resolved }; - }); - } - - constructor(props, context) { - super(props, context); - - // Internal tracking variables - this[ID] = this.generateId(); - this[CHILDREN] = []; - this[HAS_RESOLVED] = false; - this[IS_CLIENT] = false; - - this.state = this.computeState(this.props, { - pending: {}, - resolved: this.cached() || {}, - }); - - if (this.isPending(this.state)) { - this.resolve(this.state); - this[HAS_RESOLVED] = false; - } else { - this[HAS_RESOLVED] = true; + ), node); + + delete window[PAYLOAD]; } - } - cached(resolver = this) { - const id = resolver[ID]; + static resolve = function(render, initialData = {}) { + const queue = []; + + if (!isReactNative() && renderToStaticMarkup) { + renderToStaticMarkup( + { + queue.push(promise); + return Promise.resolve(true); + })}> + {render} + + ); + } - if (this.props.data.hasOwnProperty(id)) { - return { ...this.props.data[id] }; - } else if (this.context.resolver) { - return this.context.resolver.cached(resolver); - } - } + return Promise.all(queue).then((results) => { + const data = { ...initialData }; - clearData(resolver = this) { - const id = resolver[ID]; + results.forEach(({ id, resolved }) => data[id] = resolved); - if (this.props.data.hasOwnProperty(id)) { - delete this.props.data[id]; - } else if (this.context.resolver) { - return this.context.resolver.clearData(resolver); + if (Object.keys(initialData).length < Object.keys(data).length) { + return Resolver.resolve(render, data); + } + + class Resolved extends React.Component { + static displayName = "Resolved" + + render() { + return ( + + {render} + + ); + } + } + + return { data, Resolved }; + }); } - } - - componentDidMount() { - this[IS_CLIENT] = true; - } - - componentWillReceiveProps(nextProps) { - const cleanState = { - pending: {}, - resolved: {}, - }; - - const { pending, resolved } = this.computeState(nextProps, cleanState); - - // Next state will resolve async props again, but update existing sync props - const nextState = { - pending, - resolved: { ...this.state.resolved, ...resolved }, - }; - - this.setState(nextState); - } - - computeState(thisProps, nextState) { - const { props, resolve } = thisProps; - - Object.keys(resolve).forEach(name => { - // Ignore existing supplied props or existing resolved values - if (!nextState.resolved.hasOwnProperty(name)) { - const factory = resolve[name]; - const value = factory(props); - const isPromise = ( - value instanceof Promise - || - ( - ( - typeof value === "object" && value !== null - || - typeof value === "function" - ) - && - typeof value.then === "function" - ) - ); - - if (isPromise) { - nextState.pending[name] = value; + + constructor(props, context) { + super(props, context); + + // Internal tracking variables + this[ID] = this.generateId(); + this[CHILDREN] = []; + this[HAS_RESOLVED] = false; + this[IS_CLIENT] = false; + + this.state = this.computeState(this.props, { + pending: {}, + resolved: this.cached() || {}, + }); + + if (this.isPending(this.state)) { + this.resolve(this.state); + this[HAS_RESOLVED] = false; } else { - // Synchronous values are immediately assigned - nextState.resolved[name] = value; + this[HAS_RESOLVED] = true; } - } - }); + } + + cached(resolver = this) { + const id = resolver[ID]; - return nextState; - } + if (this.props.data.hasOwnProperty(id)) { + return { ...this.props.data[id] }; + } else if (this.context.resolver) { + return this.context.resolver.cached(resolver); + } + } - generateId() { - const { resolver } = this.context; + clearData(resolver = this) { + const id = resolver[ID]; - if (!resolver) { - return ".0"; + if (this.props.data.hasOwnProperty(id)) { + delete this.props.data[id]; + } else if (this.context.resolver) { + return this.context.resolver.clearData(resolver); + } } - const id = `${resolver[ID]}.${resolver[CHILDREN].length}`; + componentDidMount() { + this[IS_CLIENT] = true; + } - if (resolver && resolver[CHILDREN].indexOf(this) === -1) { - resolver[CHILDREN].push(this); + componentWillReceiveProps(nextProps) { + const cleanState = { + pending: {}, + resolved: {}, + }; + + const { pending, resolved } = this.computeState(nextProps, cleanState); + + // Next state will resolve async props again, but update existing sync props + const nextState = { + pending, + resolved: { ...this.state.resolved, ...resolved }, + }; + + this.setState(nextState); } - return id; - } + computeState(thisProps, nextState) { + const { props, resolve } = thisProps; + + Object.keys(resolve).forEach(name => { + // Ignore existing supplied props or existing resolved values + if (!nextState.resolved.hasOwnProperty(name)) { + const factory = resolve[name]; + const value = factory(props); + const isPromise = ( + value instanceof Promise + || + ( + ( + typeof value === "object" && value !== null + || + typeof value === "function" + ) + && + typeof value.then === "function" + ) + ); + + if (isPromise) { + nextState.pending[name] = value; + } else { + // Synchronous values are immediately assigned + nextState.resolved[name] = value; + } + } + }); + + return nextState; + } - getChildContext() { - return { resolver: this }; - } + generateId() { + const { resolver } = this.context; - isPending(state = this.state) { - return Object.keys(state.pending).length > 0; - } + if (!resolver) { + return ".0"; + } + + const id = `${resolver[ID]}.${resolver[CHILDREN].length}`; - isParentPending() { - const { resolver } = this.context; + if (resolver && resolver[CHILDREN].indexOf(this) === -1) { + resolver[CHILDREN].push(this); + } - if (resolver) { - return resolver.isPending() || resolver.isParentPending(); + return id; } - return false; - } + getChildContext() { + return { resolver: this }; + } - onResolve(state) { - if (this.props.onResolve) { - return this.props.onResolve(state); - } else if (this.context.resolver) { - return this.context.resolver.onResolve(state); - } else { - return state; + isPending(state = this.state) { + return Object.keys(state.pending).length > 0; } - } - render() { - // Avoid rendering until ready - if (!this[HAS_RESOLVED]) { - return false; + isParentPending() { + const { resolver } = this.context; + + if (resolver) { + return resolver.isPending() || resolver.isParentPending(); + } + + return false; } - // If render is called again (e.g. hot-reloading), re-resolve - if (this.isPending(this.state)) { - this.resolve(this.state); + onResolve(state) { + if (this.props.onResolve) { + return this.props.onResolve(state); + } else if (this.context.resolver) { + return this.context.resolver.onResolve(state); + } else { + return state; + } } - // Both those props provided by parent & dynamically resolved - return this.props.children({ - ...this.props.props, - ...this.state.resolved, - }); - } + render() { + // Avoid rendering until ready + if (!this[HAS_RESOLVED]) { + return false; + } + + // If render is called again (e.g. hot-reloading), re-resolve + if (this.isPending(this.state)) { + this.resolve(this.state); + } - resolve(state) { - const pending = Object.keys(state.pending).map(name => { - const promise = state.pending[name]; + // Both those props provided by parent & dynamically resolved + return this.props.children({ + ...this.props.props, + ...this.state.resolved, + }); + } - return { name, promise }; - }); + resolve(state) { + const pending = Object.keys(state.pending).map(name => { + const promise = state.pending[name]; - const promises = pending.map(({ promise }) => promise); + return { name, promise }; + }); - var resolving = Promise.all(promises).then(values => { - const id = this[ID]; - const resolved = values.reduce((resolved, value, i) => { - const { name } = pending[i]; + const promises = pending.map(({ promise }) => promise); - resolved[name] = value; + var resolving = Promise.all(promises).then(values => { + const id = this[ID]; + const resolved = values.reduce((resolved, value, i) => { + const { name } = pending[i]; - return resolved; - }, {}); + resolved[name] = value; - return { id, resolved }; - }); + return resolved; + }, {}); - // Resolve listeners get the current ID + resolved - resolving = this.onResolve(resolving); + return { id, resolved }; + }); - // Update current component with new data (on client) - resolving.then(({ resolved }) => { - this[HAS_RESOLVED] = true; + // Resolve listeners get the current ID + resolved + resolving = this.onResolve(resolving); - if (!this[IS_CLIENT]) { - return false; - } + // Update current component with new data (on client) + resolving.then(({ resolved }) => { + this[HAS_RESOLVED] = true; - const nextState = { - pending: {}, - resolved: { ...state.resolved, ...resolved }, - }; + if (!this[IS_CLIENT]) { + return false; + } - this.setState(nextState); - }); - } + const nextState = { + pending: {}, + resolved: { ...state.resolved, ...resolved }, + }; - shouldComponentUpdate(nextProps, nextState) { - // Prevent updating when parent is changing values - if (this.isParentPending()) { - return false; + this.setState(nextState); + }); } - // Prevent rendering until pending values are resolved - if (this.isPending(nextState)) { - this.resolve(nextState); + shouldComponentUpdate(nextProps, nextState) { + // Prevent updating when parent is changing values + if (this.isParentPending()) { + return false; + } - return false; - } + // Prevent rendering until pending values are resolved + if (this.isPending(nextState)) { + this.resolve(nextState); - // Update if we have resolved successfully - return this[HAS_RESOLVED]; - } -} + return false; + } + + // Update if we have resolved successfully + return this[HAS_RESOLVED]; + } +} \ No newline at end of file From aa84a32faaefb1f600bcafc4583d93d925fe8523 Mon Sep 17 00:00:00 2001 From: jeroenbreemhaar Date: Wed, 30 Aug 2017 14:55:01 +0200 Subject: [PATCH 4/4] ugh indenting --- src/Resolver.js | 473 ++++++++++++++++++++++++------------------------ 1 file changed, 236 insertions(+), 237 deletions(-) diff --git a/src/Resolver.js b/src/Resolver.js index 0f8aad6..426bf60 100644 --- a/src/Resolver.js +++ b/src/Resolver.js @@ -26,295 +26,294 @@ function isReactNative() { return (typeof navigator != 'undefined' && navigator.product == 'ReactNative'); } - export default class Resolver extends React.Component { - static childContextTypes = { - resolver: React.PropTypes.instanceOf(Resolver), + static childContextTypes = { + resolver: React.PropTypes.instanceOf(Resolver), + } + + static contextTypes = { + resolver: React.PropTypes.instanceOf(Resolver), + } + + static defaultProps = { + data: {}, + props: {}, + resolve: {}, + } + + static displayName = "Resolver" + + static propTypes = { + children: React.PropTypes.func.isRequired, + data: React.PropTypes.object.isRequired, + props: React.PropTypes.object, + resolve: React.PropTypes.object, + } + + static render = function(render, node, data = window[PAYLOAD]) { + ReactDOM.render(( + + {render} + + ), node); + + delete window[PAYLOAD]; + } + + static resolve = function(render, initialData = {}) { + const queue = []; + + if (!isReactNative()) { + renderToStaticMarkup( + { + queue.push(promise); + return Promise.resolve(true); + })}> + {render} + + ); } - static contextTypes = { - resolver: React.PropTypes.instanceOf(Resolver), - } + return Promise.all(queue).then((results) => { + const data = { ...initialData }; - static defaultProps = { - data: {}, - props: {}, - resolve: {}, - } + results.forEach(({ id, resolved }) => data[id] = resolved); - static displayName = "Resolver" + if (Object.keys(initialData).length < Object.keys(data).length) { + return Resolver.resolve(render, data); + } - static propTypes = { - children: React.PropTypes.func.isRequired, - data: React.PropTypes.object.isRequired, - props: React.PropTypes.object, - resolve: React.PropTypes.object, - } + class Resolved extends React.Component { + static displayName = "Resolved" - static render = function(render, node, data = window[PAYLOAD]) { - ReactDOM.render(( + render() { + return ( - {render} + {render} - ), node); - - delete window[PAYLOAD]; - } - - static resolve = function(render, initialData = {}) { - const queue = []; - - if (!isReactNative() && renderToStaticMarkup) { - renderToStaticMarkup( - { - queue.push(promise); - return Promise.resolve(true); - })}> - {render} - - ); + ); } - - return Promise.all(queue).then((results) => { - const data = { ...initialData }; - - results.forEach(({ id, resolved }) => data[id] = resolved); - - if (Object.keys(initialData).length < Object.keys(data).length) { - return Resolver.resolve(render, data); - } - - class Resolved extends React.Component { - static displayName = "Resolved" - - render() { - return ( - - {render} - - ); - } - } - - return { data, Resolved }; - }); + } + + return { data, Resolved }; + }); + } + + constructor(props, context) { + super(props, context); + + // Internal tracking variables + this[ID] = this.generateId(); + this[CHILDREN] = []; + this[HAS_RESOLVED] = false; + this[IS_CLIENT] = false; + + this.state = this.computeState(this.props, { + pending: {}, + resolved: this.cached() || {}, + }); + + if (this.isPending(this.state)) { + this.resolve(this.state); + this[HAS_RESOLVED] = false; + } else { + this[HAS_RESOLVED] = true; } + } - constructor(props, context) { - super(props, context); + cached(resolver = this) { + const id = resolver[ID]; - // Internal tracking variables - this[ID] = this.generateId(); - this[CHILDREN] = []; - this[HAS_RESOLVED] = false; - this[IS_CLIENT] = false; - - this.state = this.computeState(this.props, { - pending: {}, - resolved: this.cached() || {}, - }); - - if (this.isPending(this.state)) { - this.resolve(this.state); - this[HAS_RESOLVED] = false; - } else { - this[HAS_RESOLVED] = true; - } + if (this.props.data.hasOwnProperty(id)) { + return { ...this.props.data[id] }; + } else if (this.context.resolver) { + return this.context.resolver.cached(resolver); } + } - cached(resolver = this) { - const id = resolver[ID]; + clearData(resolver = this) { + const id = resolver[ID]; - if (this.props.data.hasOwnProperty(id)) { - return { ...this.props.data[id] }; - } else if (this.context.resolver) { - return this.context.resolver.cached(resolver); - } + if (this.props.data.hasOwnProperty(id)) { + delete this.props.data[id]; + } else if (this.context.resolver) { + return this.context.resolver.clearData(resolver); } - - clearData(resolver = this) { - const id = resolver[ID]; - - if (this.props.data.hasOwnProperty(id)) { - delete this.props.data[id]; - } else if (this.context.resolver) { - return this.context.resolver.clearData(resolver); + } + + componentDidMount() { + this[IS_CLIENT] = true; + } + + componentWillReceiveProps(nextProps) { + const cleanState = { + pending: {}, + resolved: {}, + }; + + const { pending, resolved } = this.computeState(nextProps, cleanState); + + // Next state will resolve async props again, but update existing sync props + const nextState = { + pending, + resolved: { ...this.state.resolved, ...resolved }, + }; + + this.setState(nextState); + } + + computeState(thisProps, nextState) { + const { props, resolve } = thisProps; + + Object.keys(resolve).forEach(name => { + // Ignore existing supplied props or existing resolved values + if (!nextState.resolved.hasOwnProperty(name)) { + const factory = resolve[name]; + const value = factory(props); + const isPromise = ( + value instanceof Promise + || + ( + ( + typeof value === "object" && value !== null + || + typeof value === "function" + ) + && + typeof value.then === "function" + ) + ); + + if (isPromise) { + nextState.pending[name] = value; + } else { + // Synchronous values are immediately assigned + nextState.resolved[name] = value; } - } + } + }); - componentDidMount() { - this[IS_CLIENT] = true; - } - - componentWillReceiveProps(nextProps) { - const cleanState = { - pending: {}, - resolved: {}, - }; - - const { pending, resolved } = this.computeState(nextProps, cleanState); + return nextState; + } - // Next state will resolve async props again, but update existing sync props - const nextState = { - pending, - resolved: { ...this.state.resolved, ...resolved }, - }; + generateId() { + const { resolver } = this.context; - this.setState(nextState); + if (!resolver) { + return ".0"; } - computeState(thisProps, nextState) { - const { props, resolve } = thisProps; - - Object.keys(resolve).forEach(name => { - // Ignore existing supplied props or existing resolved values - if (!nextState.resolved.hasOwnProperty(name)) { - const factory = resolve[name]; - const value = factory(props); - const isPromise = ( - value instanceof Promise - || - ( - ( - typeof value === "object" && value !== null - || - typeof value === "function" - ) - && - typeof value.then === "function" - ) - ); - - if (isPromise) { - nextState.pending[name] = value; - } else { - // Synchronous values are immediately assigned - nextState.resolved[name] = value; - } - } - }); - - return nextState; + const id = `${resolver[ID]}.${resolver[CHILDREN].length}`; + + if (resolver && resolver[CHILDREN].indexOf(this) === -1) { + resolver[CHILDREN].push(this); } - generateId() { - const { resolver } = this.context; + return id; + } - if (!resolver) { - return ".0"; - } + getChildContext() { + return { resolver: this }; + } - const id = `${resolver[ID]}.${resolver[CHILDREN].length}`; + isPending(state = this.state) { + return Object.keys(state.pending).length > 0; + } - if (resolver && resolver[CHILDREN].indexOf(this) === -1) { - resolver[CHILDREN].push(this); - } + isParentPending() { + const { resolver } = this.context; - return id; + if (resolver) { + return resolver.isPending() || resolver.isParentPending(); } - getChildContext() { - return { resolver: this }; - } + return false; + } - isPending(state = this.state) { - return Object.keys(state.pending).length > 0; + onResolve(state) { + if (this.props.onResolve) { + return this.props.onResolve(state); + } else if (this.context.resolver) { + return this.context.resolver.onResolve(state); + } else { + return state; } + } - isParentPending() { - const { resolver } = this.context; - - if (resolver) { - return resolver.isPending() || resolver.isParentPending(); - } - - return false; + render() { + // Avoid rendering until ready + if (!this[HAS_RESOLVED]) { + return false; } - onResolve(state) { - if (this.props.onResolve) { - return this.props.onResolve(state); - } else if (this.context.resolver) { - return this.context.resolver.onResolve(state); - } else { - return state; - } + // If render is called again (e.g. hot-reloading), re-resolve + if (this.isPending(this.state)) { + this.resolve(this.state); } - render() { - // Avoid rendering until ready - if (!this[HAS_RESOLVED]) { - return false; - } - - // If render is called again (e.g. hot-reloading), re-resolve - if (this.isPending(this.state)) { - this.resolve(this.state); - } + // Both those props provided by parent & dynamically resolved + return this.props.children({ + ...this.props.props, + ...this.state.resolved, + }); + } - // Both those props provided by parent & dynamically resolved - return this.props.children({ - ...this.props.props, - ...this.state.resolved, - }); - } + resolve(state) { + const pending = Object.keys(state.pending).map(name => { + const promise = state.pending[name]; - resolve(state) { - const pending = Object.keys(state.pending).map(name => { - const promise = state.pending[name]; + return { name, promise }; + }); - return { name, promise }; - }); + const promises = pending.map(({ promise }) => promise); - const promises = pending.map(({ promise }) => promise); + var resolving = Promise.all(promises).then(values => { + const id = this[ID]; + const resolved = values.reduce((resolved, value, i) => { + const { name } = pending[i]; - var resolving = Promise.all(promises).then(values => { - const id = this[ID]; - const resolved = values.reduce((resolved, value, i) => { - const { name } = pending[i]; + resolved[name] = value; - resolved[name] = value; + return resolved; + }, {}); - return resolved; - }, {}); + return { id, resolved }; + }); - return { id, resolved }; - }); + // Resolve listeners get the current ID + resolved + resolving = this.onResolve(resolving); - // Resolve listeners get the current ID + resolved - resolving = this.onResolve(resolving); + // Update current component with new data (on client) + resolving.then(({ resolved }) => { + this[HAS_RESOLVED] = true; - // Update current component with new data (on client) - resolving.then(({ resolved }) => { - this[HAS_RESOLVED] = true; + if (!this[IS_CLIENT]) { + return false; + } - if (!this[IS_CLIENT]) { - return false; - } + const nextState = { + pending: {}, + resolved: { ...state.resolved, ...resolved }, + }; - const nextState = { - pending: {}, - resolved: { ...state.resolved, ...resolved }, - }; + this.setState(nextState); + }); + } - this.setState(nextState); - }); + shouldComponentUpdate(nextProps, nextState) { + // Prevent updating when parent is changing values + if (this.isParentPending()) { + return false; } - shouldComponentUpdate(nextProps, nextState) { - // Prevent updating when parent is changing values - if (this.isParentPending()) { - return false; - } - - // Prevent rendering until pending values are resolved - if (this.isPending(nextState)) { - this.resolve(nextState); - - return false; - } + // Prevent rendering until pending values are resolved + if (this.isPending(nextState)) { + this.resolve(nextState); - // Update if we have resolved successfully - return this[HAS_RESOLVED]; + return false; } -} \ No newline at end of file + + // Update if we have resolved successfully + return this[HAS_RESOLVED]; + } +}