Skip to content

Commit

Permalink
fix: proper children reconcile for nested tags, fixes #869 (#871)
Browse files Browse the repository at this point in the history
React 15 issue.
  • Loading branch information
theKashey authored and gregberge committed Feb 25, 2018
1 parent 4b13ed1 commit 2de4e58
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 5 deletions.
8 changes: 5 additions & 3 deletions src/reconciler/hotReplacementRender.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,19 @@ const mapChildren = (children, instances) => ({
}
}

const newChildren = asArray((child.props && child.props.children) || [])
const newChildren = asArray(
(child.props && child.props.children) || child.children || [],
)
const nextChildren =
oldChildren.length && mapChildren(newChildren, oldChildren)

return {
...instanceLine,
// actually child merge is needed only for TAGs, and usually don't work for Components.
// actually child merge is needed only for "HTML TAG"s, and usually don't work for Components.
// the children from an instance or rendered children
// while children from a props is just a props.
// they could not exists. they could differ.
...(nextChildren ? { children: nextChildren } : {}),
...(nextChildren || {}),
type: child.type,
}
}),
Expand Down
42 changes: 40 additions & 2 deletions test/reconciler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,50 @@ describe('reconciler', () => {

incrementGeneration()
wrapper.setProps({ update: 'now' })
expect(First.rendered).toHaveBeenCalledTimes(4)
expect(First.rendered).toHaveBeenCalledTimes(3)
expect(Second.rendered).toHaveBeenCalledTimes(3)

incrementGeneration()
wrapper.setProps({ second: false })
expect(First.rendered).toHaveBeenCalledTimes(5)
expect(Second.rendered).toHaveBeenCalledTimes(4)

expect(First.unmounted).toHaveBeenCalledTimes(0)
expect(Second.unmounted).toHaveBeenCalledTimes(1)
})

it('should use new children branch during reconcile for full components', () => {
const First = spyComponent(() => <u>1</u>, 'test', '1')
const Second = spyComponent(() => <u>2</u>, 'test', '2')

const Section = ({ children }) => <div>{children}</div>

const App = ({ second }) => (
<div>
<div>
<Section>
<First.Component />
{second && <Second.Component />}
</Section>
</div>
</div>
)

const Mounter = ({ second }) => <App second={second} />

const wrapper = mount(<Mounter second />)

expect(First.rendered).toHaveBeenCalledTimes(1)
expect(Second.rendered).toHaveBeenCalledTimes(1)

incrementGeneration()
wrapper.setProps({ update: 'now' })
expect(First.rendered).toHaveBeenCalledTimes(3)
expect(Second.rendered).toHaveBeenCalledTimes(3)

incrementGeneration()
wrapper.setProps({ second: false })
expect(First.rendered).toHaveBeenCalledTimes(7)
expect(First.rendered).toHaveBeenCalledTimes(5)
expect(Second.rendered).toHaveBeenCalledTimes(4)

expect(First.unmounted).toHaveBeenCalledTimes(0)
Expand Down

0 comments on commit 2de4e58

Please sign in to comment.