Skip to content

Commit baa1a0b

Browse files
committed
Make sure Offscreen's ref is detached when unmounted
1 parent a8f7a96 commit baa1a0b

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

packages/react-reconciler/src/ReactFiberCommitWork.new.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ function commitLayoutEffectOnFiber(
11211121
if (flags & Ref) {
11221122
safelyAttachRef(finishedWork, finishedWork.return);
11231123
}
1124-
} else if (finishedWork.pendingProps.mode !== undefined) {
1124+
} else {
11251125
safelyDetachRef(finishedWork, finishedWork.return);
11261126
}
11271127
} else {
@@ -2148,6 +2148,8 @@ function commitDeletionEffectsOnFiber(
21482148
offscreenSubtreeWasHidden =
21492149
prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null;
21502150

2151+
safelyDetachRef(deletedFiber, nearestMountedAncestor);
2152+
21512153
recursivelyTraverseDeletionEffects(
21522154
finishedRoot,
21532155
nearestMountedAncestor,

packages/react-reconciler/src/__tests__/ReactOffscreen-test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,4 +1307,42 @@ describe('ReactOffscreen', () => {
13071307
expect(offscreenRef.current).not.toBeNull();
13081308
});
13091309
});
1310+
1311+
// @gate enableOffscreen
1312+
it('should detach ref if Offscreen is unmounted', async () => {
1313+
let offscreenRef;
1314+
1315+
function App({showOffscreen}) {
1316+
offscreenRef = useRef(null);
1317+
return showOffscreen ? (
1318+
<Offscreen
1319+
mode={'manual'}
1320+
ref={ref => {
1321+
offscreenRef.current = ref;
1322+
}}>
1323+
<div />
1324+
</Offscreen>
1325+
) : null;
1326+
}
1327+
1328+
const root = ReactNoop.createRoot();
1329+
1330+
await act(async () => {
1331+
root.render(<App showOffscreen={true} />);
1332+
});
1333+
1334+
expect(offscreenRef.current).not.toBeNull();
1335+
1336+
await act(async () => {
1337+
root.render(<App showOffscreen={false} />);
1338+
});
1339+
1340+
expect(offscreenRef.current).toBeNull();
1341+
1342+
await act(async () => {
1343+
root.render(<App showOffscreen={true} />);
1344+
});
1345+
1346+
expect(offscreenRef.current).not.toBeNull();
1347+
});
13101348
});

0 commit comments

Comments
 (0)