Skip to content

Commit

Permalink
Small refactor of image attached callbacks logic (#41701)
Browse files Browse the repository at this point in the history
Summary:

I did a hotfix for this logic in D51618512. This does a small refactor to improve the code (moving more shared code to the hook and avoiding creating a closure unnecessarily in every call to it).

Changelog: [internal]

Reviewed By: javache

Differential Revision: D51660288
  • Loading branch information
rubennorte authored and facebook-github-bot committed Nov 29, 2023
1 parent bb075d7 commit 8b9dafa
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 37 deletions.
13 changes: 2 additions & 11 deletions packages/react-native/Libraries/Image/Image.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ import type {AbstractImageAndroid, ImageAndroid} from './ImageTypes.flow';
import flattenStyle from '../StyleSheet/flattenStyle';
import StyleSheet from '../StyleSheet/StyleSheet';
import TextAncestor from '../Text/TextAncestor';
import useMergeRefs from '../Utilities/useMergeRefs';
import ImageAnalyticsTagContext from './ImageAnalyticsTagContext';
import {
unstable_getImageComponentDecorator,
useRefWithImageAttachedCallbacks,
useWrapRefWithImageAttachedCallbacks,
} from './ImageInjection';
import {getImageSourcesFromImageProps} from './ImageSourceUtils';
import {convertObjectFitToResizeMode} from './ImageUtils';
Expand Down Expand Up @@ -200,15 +199,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef(
const resizeMode =
objectFit || props.resizeMode || style?.resizeMode || 'cover';

const imageAttachedCallbacksRef = useRefWithImageAttachedCallbacks();

const actualRef =
useMergeRefs<React.ElementRef<AbstractImageAndroid> | null>(
// $FlowFixMe[incompatible-call]
forwardedRef,
// $FlowFixMe[incompatible-call]
imageAttachedCallbacksRef,
);
const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef);

return (
<ImageAnalyticsTagContext.Consumer>
Expand Down
12 changes: 2 additions & 10 deletions packages/react-native/Libraries/Image/Image.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ import type {AbstractImageIOS, ImageIOS} from './ImageTypes.flow';
import {createRootTag} from '../ReactNative/RootTag';
import flattenStyle from '../StyleSheet/flattenStyle';
import StyleSheet from '../StyleSheet/StyleSheet';
import useMergeRefs from '../Utilities/useMergeRefs';
import ImageAnalyticsTagContext from './ImageAnalyticsTagContext';
import {
unstable_getImageComponentDecorator,
useRefWithImageAttachedCallbacks,
useWrapRefWithImageAttachedCallbacks,
} from './ImageInjection';
import {getImageSourcesFromImageProps} from './ImageSourceUtils';
import {convertObjectFitToResizeMode} from './ImageUtils';
Expand Down Expand Up @@ -162,14 +161,7 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => {
};
const accessibilityLabel = props['aria-label'] ?? props.accessibilityLabel;

const imageAttachedCallbacksRef = useRefWithImageAttachedCallbacks();

const actualRef = useMergeRefs<React.ElementRef<AbstractImageIOS> | null>(
// $FlowFixMe[incompatible-call]
forwardedRef,
// $FlowFixMe[incompatible-call]
imageAttachedCallbacksRef,
);
const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef);

return (
<ImageAnalyticsTagContext.Consumer>
Expand Down
46 changes: 30 additions & 16 deletions packages/react-native/Libraries/Image/ImageInjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
Image as ImageComponent,
} from './ImageTypes.flow';

import useMergeRefs from '../Utilities/useMergeRefs';
import * as React from 'react';
import {useRef} from 'react';

Expand Down Expand Up @@ -52,24 +53,37 @@ export function unstable_unregisterImageAttachedCallback(
imageAttachedCallbacks.delete(callback);
}

export function useRefWithImageAttachedCallbacks(): React.RefSetter<ImageInstance> {
export function useWrapRefWithImageAttachedCallbacks(
forwardedRef: React.RefSetter<ImageInstance>,
): React.RefSetter<ImageInstance> {
const pendingCleanupCallbacks = useRef<Array<() => void>>([]);

const ref = useRef((node: ImageInstance | null) => {
if (node == null) {
if (pendingCleanupCallbacks.current.length > 0) {
pendingCleanupCallbacks.current.forEach(cb => cb());
pendingCleanupCallbacks.current = [];
}
} else {
imageAttachedCallbacks.forEach(imageAttachedCallback => {
const maybeCleanupCallback = imageAttachedCallback(node);
if (maybeCleanupCallback != null) {
pendingCleanupCallbacks.current.push(maybeCleanupCallback);
const imageAttachedCallbacksRef =
useRef<?(node: ImageInstance | null) => void>(null);

if (imageAttachedCallbacksRef.current == null) {
imageAttachedCallbacksRef.current = (node: ImageInstance | null): void => {
if (node == null) {
if (pendingCleanupCallbacks.current.length > 0) {
pendingCleanupCallbacks.current.forEach(cb => cb());
pendingCleanupCallbacks.current = [];
}
});
}
});
} else {
imageAttachedCallbacks.forEach(imageAttachedCallback => {
const maybeCleanupCallback = imageAttachedCallback(node);
if (maybeCleanupCallback != null) {
pendingCleanupCallbacks.current.push(maybeCleanupCallback);
}
});
}
};
}

return ref.current;
// `useMergeRefs` returns a stable ref if its arguments don't change.
return useMergeRefs<ImageInstance | null>(
// $FlowFixMe[incompatible-call]
forwardedRef,
// $FlowFixMe[incompatible-call]
imageAttachedCallbacksRef.current,
);
}

0 comments on commit 8b9dafa

Please sign in to comment.