Skip to content

Commit

Permalink
Recreate unkeyed functional components when they change position.
Browse files Browse the repository at this point in the history
With keyed children we can confidently track them as they move
throughout an array of components. When this happens with unkeyed
functional components we should not risk reusing the state as that
could possibly make us re-use state in unrelated components, as
seen in #2949.
  • Loading branch information
JoviDeCroock committed Nov 10, 2024
1 parent 76d6d4d commit 4c8da0e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/diff/children.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,9 @@ function findMatchingIndex(
// if the oldVNode was null or matched, then there could needs to be at least
// 1 (aka `remainingOldChildren > 0`) children to find and compare against.
let shouldSearch =
(typeof type !== 'function' || type === Fragment || key) &&
remainingOldChildren >
(oldVNode != null && (oldVNode._flags & MATCHED) === 0 ? 1 : 0);
(oldVNode != null && (oldVNode._flags & MATCHED) === 0 ? 1 : 0);

if (
oldVNode === null ||
Expand Down
31 changes: 31 additions & 0 deletions test/browser/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,37 @@ describe('render()', () => {
);
});

// #2949
it('should not swap unkeyed chlildren', () => {
class X extends Component {
constructor(props) {
super(props);
this.name = props.name;
}
render() {
return <p>{this.name}</p>;
}
}

function Foo({ condition }) {
return (
<div>
{condition ? '' : <X name="A" />}
{condition ? <X name="B" /> : ''}
</div>
);
}

render(<Foo />, scratch);
expect(scratch.textContent).to.equal('A');

render(<Foo condition />, scratch);
expect(scratch.textContent).to.equal('B');

render(<Foo />, scratch);
expect(scratch.textContent).to.equal('A');
});

it('handle shuffled (stress test)', () => {
function randomize(arr) {
for (let i = arr.length - 1; i > 0; i--) {
Expand Down

0 comments on commit 4c8da0e

Please sign in to comment.