Skip to content

Commit a2d0cb4

Browse files
committed
Fixes bug where children were continuously traversed despite a visitor result indicating the desire to stop traversal.
1 parent aebc730 commit a2d0cb4

2 files changed

Lines changed: 46 additions & 21 deletions

File tree

src/__tests__/index.test.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,25 @@ describe('reactTreeWalker', () => {
9090
})
9191
})
9292

93+
it('promise based visitor stops resolving', () => {
94+
const tree = createTree(true)
95+
const actual = []
96+
// eslint-disable-next-line no-unused-vars
97+
const visitor = (element, instance, context) => {
98+
if (instance && typeof instance.getSomething === 'function') {
99+
return instance.getSomething().then(something => {
100+
actual.push(something)
101+
return something !== 4
102+
})
103+
}
104+
return true
105+
}
106+
return reactTreeWalker(tree, visitor).then(() => {
107+
const expected = [1, 2, 4, 3]
108+
expect(actual).toEqual(expected)
109+
})
110+
})
111+
93112
it('componentWillMount & setState', () => {
94113
let actual = {}
95114

@@ -101,7 +120,9 @@ describe('reactTreeWalker', () => {
101120

102121
componentWillMount() {
103122
this.setState({ foo: 'bar' })
104-
this.setState((state, props) => ({ other: `I am ${props.value} ${state.foo}` }))
123+
this.setState((state, props) => ({
124+
other: `I am ${props.value} ${state.foo}`,
125+
}))
105126
}
106127

107128
render() {

src/index.js

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,8 @@ export default function reactTreeWalker(
6666
options = defaultOptions,
6767
) {
6868
return new Promise(resolve => {
69-
const doVisit = (getChildren, visitorResult, childContext) => {
70-
const doTraverse = shouldContinue => {
71-
if (!shouldContinue) {
72-
// We recieved a false, which indicates a desire to stop traversal.
73-
resolve()
74-
}
75-
69+
const doVisit = (getChildren, visitResult, childContext) => {
70+
const visitChildren = () => {
7671
const child = ensureChild(getChildren())
7772
const theChildContext =
7873
typeof childContext === 'function' ? childContext() : childContext
@@ -97,25 +92,34 @@ export default function reactTreeWalker(
9792
}
9893
}
9994

100-
if (visitorResult === false) {
95+
if (visitResult === false) {
10196
// Visitor returned false, indicating a desire to not traverse.
10297
resolve()
103-
} else if (isPromise(visitorResult)) {
98+
} else if (isPromise(visitResult)) {
10499
// We need to execute the result and pass it's result through to our
105100
// continuer.
106-
visitorResult.then(doTraverse).catch(e => {
107-
console.log(
108-
'Error occurred in Promise based visitor result provided to react-tree-walker.',
109-
)
110-
if (e) {
111-
console.log(e)
112-
if (e.stack) {
113-
console.log(e.stack)
101+
visitResult
102+
.then(promiseResult => {
103+
if (promiseResult === false) {
104+
resolve()
105+
} else {
106+
visitChildren()
114107
}
115-
}
116-
})
108+
})
109+
.catch(e => {
110+
console.log(
111+
'Error occurred in Promise based visitor provided to react-tree-walker.',
112+
)
113+
if (e) {
114+
console.log(e)
115+
if (e.stack) {
116+
console.log(e.stack)
117+
}
118+
}
119+
})
117120
} else {
118-
doTraverse(true)
121+
// Visitor returned true, indicating a desire to continue traversing.
122+
visitChildren()
119123
}
120124
}
121125

0 commit comments

Comments
 (0)