@@ -54,8 +54,6 @@ const ensureChild = child =>
5454 ? ensureChild ( child . render ( ) )
5555 : child
5656
57- const isPromise = x => x != null && typeof x . then === 'function'
58-
5957// Recurse an React Element tree, running visitor on each element.
6058// If visitor returns `false`, don't call the element's render function
6159// or recurse into its child elements
@@ -79,53 +77,43 @@ export default function reactTreeWalker(
7977
8078 const recursive = ( currentElement , currentContext ) =>
8179 new Promise ( innerResolve => {
82- const doVisit = ( getChildren , visitResult , childContext ) => {
83- const visitChildren = ( ) => {
84- const child = ensureChild ( getChildren ( ) )
85- const theChildContext =
86- typeof childContext === 'function' ? childContext ( ) : childContext
87-
88- if ( child == null ) {
89- // If no children then we can't traverse. We've reached the leaf.
90- innerResolve ( )
91- } else if ( Children . count ( child ) ) {
92- // If its a react Children collection we need to breadth-first
93- // traverse each of them.
94- const mapper = aChild =>
95- aChild ? recursive ( aChild , theChildContext ) : undefined
96- const children = Children . map ( child , cur => cur )
97- // pMapSeries allows us to do depth-first traversal. Thanks @sindresorhus!
98- pMapSeries ( children , mapper )
99- . then ( innerResolve , reject )
100- . catch ( reject )
101- } else {
102- // Otherwise we pass the individual child to the next recursion.
103- recursive ( child , theChildContext )
104- . then ( innerResolve , reject )
105- . catch ( reject )
106- }
107- }
108-
109- if ( visitResult === false ) {
110- // Visitor returned false, indicating a desire to not traverse.
111- innerResolve ( )
112- } else if ( isPromise ( visitResult ) ) {
113- // We need to execute the result and pass it's result through to our
114- // continuer.
115- visitResult
116- . then ( promiseResult => {
117- if ( promiseResult === false ) {
80+ const visitCurrentElement = ( childResolver , context , compInstance ) =>
81+ Promise . resolve ( safeVisitor ( currentElement , compInstance , context ) )
82+ . then ( result => {
83+ if ( result === false ) {
84+ // Visitor returned false, indicating a desire to not visit
85+ // the children of the current element, so we will just resolve.
86+ innerResolve ( )
87+ } else {
88+ // A false wasn't returned so we will attempt to visit the children
89+ // for the current element.
90+ const child = ensureChild ( childResolver ( ) )
91+ const theChildContext =
92+ typeof context === 'function' ? context ( ) : context
93+
94+ if ( child == null ) {
95+ // No children. We've reached the end of this branch. resolve.
11896 innerResolve ( )
97+ } else if ( Children . count ( child ) ) {
98+ // If its a react Children collection we need to breadth-first
99+ // traverse each of them, and pMapSeries allows us to do a
100+ // depth-first traversal that respects Promises. Thanks @sindresorhus!
101+ pMapSeries (
102+ Children . map ( child , cur => cur ) ,
103+ aChild =>
104+ aChild ? recursive ( aChild , theChildContext ) : undefined ,
105+ )
106+ . then ( innerResolve , reject )
107+ . catch ( reject )
119108 } else {
120- visitChildren ( )
109+ // Otherwise we pass the individual child to the next recursion.
110+ recursive ( child , theChildContext )
111+ . then ( innerResolve , reject )
112+ . catch ( reject )
121113 }
122- } )
123- . catch ( reject )
124- } else {
125- // Visitor returned true, indicating a desire to continue traversing.
126- visitChildren ( )
127- }
128- }
114+ }
115+ } )
116+ . catch ( reject )
129117
130118 // Is this element a Component?
131119 if ( typeof currentElement . type === 'function' ) {
@@ -164,62 +152,46 @@ export default function reactTreeWalker(
164152 instance . state = Object . assign ( { } , instance . state , newState )
165153 }
166154
167- doVisit (
155+ visitCurrentElement (
168156 ( ) => {
169- // Call componentWillMount if it exists.
170157 if ( instance . componentWillMount ) {
171158 instance . componentWillMount ( )
172159 }
173-
174- const children = instance . render ( )
175-
176- if (
177- options . componentWillUnmount &&
178- instance . componentWillUnmount
179- ) {
180- try {
181- instance . componentWillUnmount ( )
182- } catch ( err ) {
183- // This is an experimental feature, we don't want to break
184- // the bootstrapping process, but lets warn the user it
185- // occurred.
186- console . warn (
187- 'Error calling componentWillUnmount whilst walking your react tree' ,
188- )
189- console . warn ( err )
190- }
191- }
192-
193- return children
160+ return instance . render ( )
194161 } ,
195- safeVisitor ( currentElement , instance , currentContext ) ,
196162 ( ) =>
197- // Ensure the child context is initialised if it is available. We will
198- // need to pass it down the tree.
163+ // Ensure the child context is initialised if it is available.
164+ // We will need to pass it down the tree.
199165 instance . getChildContext
200166 ? Object . assign (
201167 { } ,
202168 currentContext ,
203169 instance . getChildContext ( ) ,
204170 )
205171 : currentContext ,
206- )
172+ instance ,
173+ ) . then ( ( ) => {
174+ if (
175+ options . componentWillUnmount &&
176+ instance . componentWillUnmount
177+ ) {
178+ instance . componentWillUnmount ( )
179+ }
180+ } )
207181 } else {
208182 // Stateless Functional Component
209- doVisit (
183+ visitCurrentElement (
210184 ( ) => Component ( props , currentContext ) ,
211- safeVisitor ( currentElement , null , currentContext ) ,
212185 currentContext ,
213186 )
214187 }
215188 } else {
216189 // This must be a basic element, such as a string or dom node.
217- doVisit (
190+ visitCurrentElement (
218191 ( ) =>
219192 currentElement . props && currentElement . props . children
220193 ? currentElement . props . children
221194 : undefined ,
222- safeVisitor ( currentElement , null , currentContext ) ,
223195 currentContext ,
224196 )
225197 }
0 commit comments