11/* @flow */
2+ // Extracted from: https://github.com/apollostack/react-apollo/blob/master/src/server.ts
23
34// eslint-disable-next-line import/no-extraneous-dependencies
45import { Children , Element } from 'react' ;
@@ -8,6 +9,8 @@ type Context = { [key: string]: any; };
89type ElementVisitor =
910 ( element : React$Element , instance : ?Function , context : Context ) => boolean | void ;
1011
12+ export const isPromise = ( x : any ) => typeof x === 'object' && typeof x . then === 'function' ;
13+
1114// Recurse an React Element tree, running visitor on each element.
1215// If visitor returns `false`, don't call the element's render function
1316// or recurse into its child elements
@@ -16,16 +19,14 @@ export default function reactTreeWalker(
1619 visitor : ElementVisitor ,
1720 context : Context = { } ,
1821) {
19- const Component = element . type ;
20-
21- // a stateless functional component or a class
22- if ( typeof Component === 'function' ) {
22+ // Is this element a Component?
23+ if ( typeof element . type === 'function' ) {
24+ const Component = element . type ;
2325 const props = Object . assign ( { } , Component . defaultProps , element . props ) ;
2426 let childContext = context ;
2527 let child ;
2628
27- // Are we are a react class?
28- // http://bit.ly/2j9Ifk3
29+ // Is this a class component? (http://bit.ly/2j9Ifk3)
2930 const isReactClassComponent = Component . prototype &&
3031 ( Component . prototype . isReactComponent || Component . prototype . isPureReactComponent ) ;
3132
@@ -35,43 +36,57 @@ export default function reactTreeWalker(
3536 instance . props = instance . props || props ;
3637 instance . context = instance . context || context ;
3738
38- // Override setState to just change the state, not queue up an update.
39- // (we can't do the default React thing as we aren't mounted "properly"
40- // however, we don't need to re-render as well only support setState in
41- // componentWillMount, which happens *before* render).
39+ // Make the setState synchronous.
4240 instance . setState = ( newState ) => {
4341 instance . state = Object . assign ( { } , instance . state , newState ) ;
4442 } ;
4543
44+ // Call componentWillMount if it exists.
4645 if ( instance . componentWillMount ) {
4746 instance . componentWillMount ( ) ;
4847 }
4948
49+ // Ensure the child context is initialised if it is available. We will
50+ // need to pass it down the tree.
5051 if ( instance . getChildContext ) {
5152 childContext = Object . assign ( { } , context , instance . getChildContext ( ) ) ;
5253 }
5354
55+ // Hit up our visitor!
5456 if ( visitor ( element , instance , context ) === false ) {
57+ // Visitor returned false, indicating a desire to not traverse.
5558 return ;
5659 }
5760
61+ // Get the render output as the child.
5862 child = instance . render ( ) ;
59- } else { // just a stateless functional
63+ } else {
64+ // Stateless Functional Component
65+
66+ // Hit up our visitor!
6067 if ( visitor ( element , null , context ) === false ) {
68+ // Visitor returned false, indicating a desire to not traverse.
6169 return ;
6270 }
6371
72+ // Get the output for the function, as the child.
6473 child = Component ( props , context ) ;
6574 }
6675
76+ // Only continue walking if a child exists.
6777 if ( child ) {
6878 reactTreeWalker ( child , visitor , childContext ) ;
6979 }
70- } else { // a basic string or dom element, just get children
80+ } else {
81+ // This must be a basic element, such as a string or dom node.
82+
83+ // Hit up our visitor!
7184 if ( visitor ( element , null , context ) === false ) {
85+ // Visitor returned false, indicating a desire to not traverse.
7286 return ;
7387 }
7488
89+ // If the element has children then we will walk them.
7590 if ( element . props && element . props . children ) {
7691 Children . forEach ( element . props . children , ( child : any ) => {
7792 if ( child ) {
0 commit comments