Skip to content

Commit 73cf5d8

Browse files
committed
Return disconnected when fragment instance is unmounted
1 parent 6547b27 commit 73cf5d8

File tree

2 files changed

+67
-18
lines changed

2 files changed

+67
-18
lines changed

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2628,8 +2628,14 @@ FragmentInstance.prototype.compareDocumentPosition = function (
26282628
this: FragmentInstanceType,
26292629
otherNode: Instance,
26302630
): number {
2631+
const parentHostInstance = getFragmentParentHostInstance(this._fragmentFiber);
2632+
if (parentHostInstance === null) {
2633+
return Node.DOCUMENT_POSITION_DISCONNECTED;
2634+
}
2635+
26312636
const children: Array<Instance> = [];
26322637
traverseFragmentInstance(this._fragmentFiber, collectChildren, children);
2638+
26332639
if (children.length === 0) {
26342640
return (
26352641
Node.DOCUMENT_POSITION_DISCONNECTED |

packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -969,24 +969,16 @@ describe('FragmentRefs', () => {
969969

970970
describe('compareDocumentPosition', () => {
971971
function expectPosition(position, spec) {
972-
expect((position & Node.DOCUMENT_POSITION_PRECEDING) !== 0).toBe(
973-
spec.preceding,
974-
);
975-
expect((position & Node.DOCUMENT_POSITION_FOLLOWING) !== 0).toBe(
976-
spec.following,
977-
);
978-
expect((position & Node.DOCUMENT_POSITION_CONTAINS) !== 0).toBe(
979-
spec.contains,
980-
);
981-
expect((position & Node.DOCUMENT_POSITION_CONTAINED_BY) !== 0).toBe(
982-
spec.containedBy,
983-
);
984-
expect((position & Node.DOCUMENT_POSITION_DISCONNECTED) !== 0).toBe(
985-
spec.disconnected,
986-
);
987-
expect(
988-
(position & Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC) !== 0,
989-
).toBe(spec.implementationSpecific);
972+
const positionResult = {
973+
following: (position & Node.DOCUMENT_POSITION_FOLLOWING) !== 0,
974+
preceding: (position & Node.DOCUMENT_POSITION_PRECEDING) !== 0,
975+
contains: (position & Node.DOCUMENT_POSITION_CONTAINS) !== 0,
976+
containedBy: (position & Node.DOCUMENT_POSITION_CONTAINED_BY) !== 0,
977+
disconnected: (position & Node.DOCUMENT_POSITION_DISCONNECTED) !== 0,
978+
implementationSpecific:
979+
(position & Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC) !== 0,
980+
};
981+
expect(positionResult).toEqual(spec);
990982
}
991983
// @gate enableFragmentRefs
992984
it('returns the relationship between the fragment instance and a given node', async () => {
@@ -1265,5 +1257,56 @@ describe('FragmentRefs', () => {
12651257
},
12661258
);
12671259
});
1260+
1261+
// @gate enableFragmentRefs
1262+
it('returns disconnected for comparison with an unmounted fragment instance', async () => {
1263+
const fragmentRef = React.createRef();
1264+
const containerRef = React.createRef();
1265+
const root = ReactDOMClient.createRoot(container);
1266+
1267+
function Test({mount}) {
1268+
return (
1269+
<div ref={containerRef}>
1270+
{mount && (
1271+
<Fragment ref={fragmentRef}>
1272+
<div></div>
1273+
</Fragment>
1274+
)}
1275+
</div>
1276+
);
1277+
}
1278+
1279+
await act(() => root.render(<Test mount={true} />));
1280+
1281+
const fragmentHandle = fragmentRef.current;
1282+
1283+
expectPosition(
1284+
fragmentHandle.compareDocumentPosition(containerRef.current),
1285+
{
1286+
preceding: true,
1287+
following: false,
1288+
contains: true,
1289+
containedBy: false,
1290+
disconnected: false,
1291+
implementationSpecific: false,
1292+
},
1293+
);
1294+
1295+
await act(() => {
1296+
root.render(<Test mount={false} />);
1297+
});
1298+
1299+
expectPosition(
1300+
fragmentHandle.compareDocumentPosition(containerRef.current),
1301+
{
1302+
preceding: false,
1303+
following: false,
1304+
contains: false,
1305+
containedBy: false,
1306+
disconnected: true,
1307+
implementationSpecific: false,
1308+
},
1309+
);
1310+
});
12681311
});
12691312
});

0 commit comments

Comments
 (0)