Skip to content

Commit

Permalink
Fix error when trying to unobserve detached targets in IntersectionOb…
Browse files Browse the repository at this point in the history
…server

Summary:
Yet another problem caused by React being too aggressive cleaning up detached fibers. This fixes a problem in `IntersectionObserver` when trying to `unobserve` detached targets. In that case we didn't have access to its shadow node anymore, so we didn't have a way to unobserve in native. This keeps an additional mapping in JS to do the conversion even after detached.

Changelog: [internal]

Differential Revision: D51257960
  • Loading branch information
rubennorte authored and facebook-github-bot committed Nov 13, 2023
1 parent 951bb72 commit dc36601
Showing 1 changed file with 13 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ function unsetTargetForInstanceHandle(instanceHandle: mixed): void {
instanceHandleToTargetMap.delete(key);
}

// The mapping between ReactNativeElement and their corresponding shadow nodes
// also needs to be kept here because React removes the link when unmounting.
const targetToShadowNodeMap: WeakMap<
ReactNativeElement,
ReturnType<typeof getShadowNode>,
> = new WeakMap();

/**
* Registers the given intersection observer and returns a unique ID for it,
* which is required to start observing targets.
Expand Down Expand Up @@ -151,6 +158,9 @@ export function observe({
// access it even after the instance handle has been unmounted.
setTargetForInstanceHandle(instanceHandle, target);

// Same for the mapping between the target and its shadow node.
targetToShadowNodeMap.set(target, targetShadowNode);

if (!isConnected) {
NativeIntersectionObserver.connect(notifyIntersectionObservers);
isConnected = true;
Expand Down Expand Up @@ -182,7 +192,7 @@ export function unobserve(
return;
}

const targetShadowNode = getShadowNode(target);
const targetShadowNode = targetToShadowNodeMap.get(target);
if (targetShadowNode == null) {
console.error(
'IntersectionObserverManager: could not find reference to host node from target',
Expand All @@ -204,8 +214,9 @@ export function unobserve(
);

// We can guarantee we won't receive any more entries for this target,
// so we don't need to keep the mapping anymore.
// so we don't need to keep the mappings anymore.
unsetTargetForInstanceHandle(instanceHandle);
targetToShadowNodeMap.delete(target);
}

/**
Expand Down

0 comments on commit dc36601

Please sign in to comment.