diff --git a/src/reanimated2/hook/useAnimatedStyle.ts b/src/reanimated2/hook/useAnimatedStyle.ts index 58626614a0c..59b1c173158 100644 --- a/src/reanimated2/hook/useAnimatedStyle.ts +++ b/src/reanimated2/hook/useAnimatedStyle.ts @@ -8,9 +8,8 @@ import NativeReanimatedModule from '../NativeReanimated'; import { useSharedValue } from './useSharedValue'; import { buildWorkletsHash, - getStyleWithoutAnimations, isAnimated, - styleDiff, + shallowEqual, validateAnimatedStyles, } from './utils'; import { DependencyList, Descriptor } from './commonTypes'; @@ -30,6 +29,7 @@ import { BasicWorkletFunctionOptional, NestedObjectValues, SharedValue, + StyleProps, } from '../commonTypes'; export interface AnimatedStyleResult { viewDescriptors: ViewDescriptorsSet; @@ -183,8 +183,10 @@ function styleUpdater( const animations = state.animations ?? {}; const newValues = updater() ?? {}; const oldValues = state.last; + const nonAnimatedNewValues: StyleProps = {}; let hasAnimations = false; + let hasNonAnimatedValues = false; for (const key in newValues) { const value = newValues[key]; if (isAnimated(value)) { @@ -192,6 +194,8 @@ function styleUpdater( animations[key] = value; hasAnimations = true; } else { + hasNonAnimatedValues = true; + nonAnimatedNewValues[key] = value; delete animations[key]; } } @@ -244,21 +248,19 @@ function styleUpdater( requestAnimationFrame(frame); } } - state.last = Object.assign({}, oldValues, newValues); - const style = getStyleWithoutAnimations(state.last); - if (style) { - updateProps(viewDescriptors, style, maybeViewRef); + + if (hasNonAnimatedValues) { + updateProps(viewDescriptors, nonAnimatedNewValues, maybeViewRef); } } else { state.isAnimationCancelled = true; state.animations = []; - const diff = styleDiff(oldValues, newValues); - state.last = Object.assign({}, oldValues, newValues); - if (diff) { + if (!shallowEqual(oldValues, newValues)) { updateProps(viewDescriptors, newValues, maybeViewRef); } } + state.last = newValues; } function jestStyleUpdater( @@ -352,13 +354,12 @@ function jestStyleUpdater( } // calculate diff - const diff = styleDiff(oldValues, newValues); - state.last = Object.assign({}, oldValues, newValues); + state.last = newValues; - if (Object.keys(diff).length !== 0) { + if (!shallowEqual(oldValues, newValues)) { updatePropsJestWrapper( viewDescriptors, - diff, + newValues, maybeViewRef, animatedStyle, adapters diff --git a/src/reanimated2/hook/utils.ts b/src/reanimated2/hook/utils.ts index 04d064918ad..3d5abe015ed 100644 --- a/src/reanimated2/hook/utils.ts +++ b/src/reanimated2/hook/utils.ts @@ -5,7 +5,6 @@ import { Context, NativeEvent, NestedObjectValues, - StyleProps, WorkletFunction, AnimationObject, } from '../commonTypes'; @@ -178,44 +177,22 @@ export function isAnimated(prop: NestedObjectValues): boolean { return false; } -export function styleDiff( - oldStyle: AnimatedStyle, - newStyle: AnimatedStyle -): Partial { +export function shallowEqual(a: any, b: any) { 'worklet'; - const diff: any = {}; - for (const key in oldStyle) { - if (newStyle[key] === undefined) { - diff[key] = null; - } - } - for (const key in newStyle) { - const value = newStyle[key]; - const oldValue = oldStyle[key]; - - if (isAnimated(value)) { - // do nothing - continue; - } - if (oldValue !== value) { - diff[key] = value; + let aKeys = 0; + for (const key in a) { + aKeys += 1; + if (b[key] === a[key]) { + return false; } } - return diff; -} - -export function getStyleWithoutAnimations(newStyle: AnimatedStyle): StyleProps { - 'worklet'; - const diff: StyleProps = {}; - - for (const key in newStyle) { - const value = newStyle[key]; - if (isAnimated(value)) { - continue; - } - diff[key] = value; + // we use for loop here, as we want to avoid calling Object.keys that allocates new array + let bKeys = 0; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const key in b) { + bKeys += 1; } - return diff; + return aKeys === bKeys; } export const validateAnimatedStyles = (styles: AnimatedStyle): void => {