From bc4dee94fedd7326f61cd4c1f14c7af5449a2f53 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Mon, 3 Feb 2025 16:49:40 -0800 Subject: [PATCH] Animated: Stabilize `allowlist` in `useAnimatedPropsMemo` (#49140) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49140 Similar to the change made in `useAnimatedProps`, except for `useAnimatedPropsMemo`. (This is just split out to make the changes easier to review.) Changelog: [Internal] Reviewed By: javache Differential Revision: D69058338 fbshipit-source-id: 033853673d8fe1442b37bb0c0adc7cb22557c334 --- ...js => createAnimatedPropsMemoHook-test.js} | 2 +- .../animated/createAnimatedPropsHook.js | 6 +- ...Memo.js => createAnimatedPropsMemoHook.js} | 69 ++++++++++--------- 3 files changed, 43 insertions(+), 34 deletions(-) rename packages/react-native/src/private/animated/__tests__/{useAnimatedPropsMemo-test.js => createAnimatedPropsMemoHook-test.js} (99%) rename packages/react-native/src/private/animated/{useAnimatedPropsMemo.js => createAnimatedPropsMemoHook.js} (90%) diff --git a/packages/react-native/src/private/animated/__tests__/useAnimatedPropsMemo-test.js b/packages/react-native/src/private/animated/__tests__/createAnimatedPropsMemoHook-test.js similarity index 99% rename from packages/react-native/src/private/animated/__tests__/useAnimatedPropsMemo-test.js rename to packages/react-native/src/private/animated/__tests__/createAnimatedPropsMemoHook-test.js index 40c1c2c2f99..51f71851e17 100644 --- a/packages/react-native/src/private/animated/__tests__/useAnimatedPropsMemo-test.js +++ b/packages/react-native/src/private/animated/__tests__/createAnimatedPropsMemoHook-test.js @@ -14,7 +14,7 @@ import AnimatedValue from '../../../../Libraries/Animated/nodes/AnimatedValue'; import { areCompositeKeysEqual, createCompositeKeyForProps, -} from '../useAnimatedPropsMemo'; +} from '../createAnimatedPropsMemoHook'; describe('createCompositeKeyForProps', () => { describe('with allowlist', () => { diff --git a/packages/react-native/src/private/animated/createAnimatedPropsHook.js b/packages/react-native/src/private/animated/createAnimatedPropsHook.js index 9c608dd7ebb..2c565b926e2 100644 --- a/packages/react-native/src/private/animated/createAnimatedPropsHook.js +++ b/packages/react-native/src/private/animated/createAnimatedPropsHook.js @@ -18,8 +18,8 @@ import AnimatedValue from '../../../Libraries/Animated/nodes/AnimatedValue'; import {isPublicInstance as isFabricPublicInstance} from '../../../Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstanceUtils'; import useRefEffect from '../../../Libraries/Utilities/useRefEffect'; import * as ReactNativeFeatureFlags from '../featureflags/ReactNativeFeatureFlags'; +import {createAnimatedPropsMemoHook} from './createAnimatedPropsMemoHook'; import NativeAnimatedHelper from './NativeAnimatedHelper'; -import {useAnimatedPropsMemo} from './useAnimatedPropsMemo'; import { useCallback, useEffect, @@ -49,6 +49,8 @@ type AnimatedValueListeners = Array<{ export default function createAnimatedPropsHook( allowlist: ?AnimatedPropsAllowlist, ): AnimatedPropsHook { + const useAnimatedPropsMemo = createAnimatedPropsMemoHook(allowlist); + return function useAnimatedProps( props: TProps, ): [ReducedProps, CallbackRef] { @@ -58,7 +60,7 @@ export default function createAnimatedPropsHook( const node = useAnimatedPropsMemo( () => new AnimatedProps(props, () => onUpdateRef.current?.(), allowlist), - [allowlist, props], + props, ); const useNativePropsInFabric = diff --git a/packages/react-native/src/private/animated/useAnimatedPropsMemo.js b/packages/react-native/src/private/animated/createAnimatedPropsMemoHook.js similarity index 90% rename from packages/react-native/src/private/animated/useAnimatedPropsMemo.js rename to packages/react-native/src/private/animated/createAnimatedPropsMemoHook.js index 1f093c205a9..e12cb40ab1c 100644 --- a/packages/react-native/src/private/animated/useAnimatedPropsMemo.js +++ b/packages/react-native/src/private/animated/createAnimatedPropsMemoHook.js @@ -48,43 +48,50 @@ type $ReadOnlyCompositeKeyComponent = | $ReadOnlyArray<$ReadOnlyCompositeKeyComponent | null> | $ReadOnly<{[string]: $ReadOnlyCompositeKeyComponent}>; +type AnimatedPropsMemoHook = ( + () => AnimatedProps, + props: $ReadOnly<{[string]: mixed}>, +) => AnimatedProps; + /** - * A hook that returns an `AnimatedProps` object that is memoized based on the - * subset of `props` that are instances of `AnimatedNode` or `AnimatedEvent`. + * Creates a hook that returns an `AnimatedProps` object that is memoized based + * on the subset of `props` that are instances of `AnimatedNode` or + * `AnimatedEvent`. */ -export function useAnimatedPropsMemo( - create: () => AnimatedProps, - // TODO: Make this two separate arguments after the experiment is over. This - // is only an array-like structure to make it easier to experiment with this - // and `useMemo`. - [allowlist, props]: [?AnimatedPropsAllowlist, {[string]: mixed}], -): AnimatedProps { - const compositeKey = useMemo( - () => createCompositeKeyForProps(props, allowlist), - [allowlist, props], - ); +export function createAnimatedPropsMemoHook( + allowlist: ?AnimatedPropsAllowlist, +): AnimatedPropsMemoHook { + return function useAnimatedPropsMemo( + create: () => AnimatedProps, + props: $ReadOnly<{[string]: mixed}>, + ): AnimatedProps { + const compositeKey = useMemo( + () => createCompositeKeyForProps(props, allowlist), + [props], + ); - const [state, setState] = useState<{ - allowlist: ?AnimatedPropsAllowlist, - compositeKey: $ReadOnlyCompositeKey | null, - value: AnimatedProps, - }>(() => ({ - allowlist, - compositeKey, - value: create(), - })); - - if ( - state.allowlist !== allowlist || - !areCompositeKeysEqual(state.compositeKey, compositeKey) - ) { - setState({ + const [state, setState] = useState<{ + allowlist: ?AnimatedPropsAllowlist, + compositeKey: $ReadOnlyCompositeKey | null, + value: AnimatedProps, + }>(() => ({ allowlist, compositeKey, value: create(), - }); - } - return state.value; + })); + + if ( + state.allowlist !== allowlist || + !areCompositeKeysEqual(state.compositeKey, compositeKey) + ) { + setState({ + allowlist, + compositeKey, + value: create(), + }); + } + return state.value; + }; } /**