microsoft / microsoft/react-native-windows

Natively driven translation transforms using Animated.Value expected results do not match JS driven if initialValue is non-zero

Open
#13,452 1 comment 0 reactions 1 assignee View on GitHub

@chrisglein is already working on this.

Since Jul 18, 2024.

Area: Animation bug Old Architecture Partner: Microsoft Workstream: Component Parity
Dominant language
C++
Stars
17.3k
Forks
1.2k
Avg merge
1d 13h
Merged PRs (30d)
33

Description

Problem Description

There are a few bugs at play, though all possibly caused by the same issue. When attempting to use natively driven Animated.Value to transform and translate a view from a non-zero starting point, the view is rendered in the incorrect location. With work arounds we can get this to work, but there is then a further bug. If the transform value needs to be modified before or after an animation, setValue cannot be called on the Value instance. Furthermore, to fix this we can opt-out of Composition native animation, but there is no publically available way to create an Animated.Value instance starting as a natively driven non-composition value.

So to summarize the three bugs.

  1. Animated.Value cannot be create with a non-zero value and be natively driven
  2. Animated.Value cannot have setValue called when natively driven
  3. new Animated.Value(initialValue, { useNativeDriver: true, platformConfig: { useComposition: false }}) will not pass the platform config down to native. This appears to be due to React Native's AnimatedValue constructor calling __makeNative() with no params unlike other Animated variants that do pass in the platform config.
Steps To Reproduce

First bug:

  1. Create a natively driven animated value with a non-zero initialValue. const translateYValue= useAnimatedValue(100, { useNativeDriver: true };
  2. Use this value on an Animated.View style transform: <Animated.View style={{ transform: [{ translateY: translateYValue }] }}/>

Second bug:

  1. Create a natively driven animated value with a zero initialValue. const translateYValue= useAnimatedValue(0, { useNativeDriver: true };
  2. On mount, set the value to anything else useEffect(() => translateYValue.setValue(100), []);

Third bug:

1. const translateYValue = useAnimatedValue(0, { useNativeDriver: true, platformConfig: { useComposition: false }});
Expected Results

Bug #1: Value performs like JS or non-composition animation. As a developer, I can use animated values that have a non-zero initial value

Bug #2: Value performs like JS or non-composition animation. As a developer, I can set the instance's value at any point while mounted to change the value natively

Bug #3: I have a way to turn off composition animation per animated node. Instead, I have to use a hidden function __setPlatformConfig.

CLI version

12.3.6, 13.6.8

Environment
I have reproduced this in two environments.

React Native 73 App

System:
  OS: Windows 11 10.0.22631
  CPU: (24) x64 13th Gen Intel(R) Core(TM) i7-13700K
  Memory: 35.61 GB / 63.70 GB
Binaries:
  Node:
    version: 20.15.1
    path: C:\Program Files\nodejs\node.EXE
  Yarn:
    version: 1.22.19
    path: C:\Program Files (x86)\Yarn\bin\yarn.CMD
  npm:
    version: 10.7.0
    path: C:\Program Files\nodejs\npm.CMD
  Watchman: Not Found
SDKs:
  Android SDK: Not Found
  Windows SDK:
    AllowDevelopmentWithoutDevLicense: Enabled
    AllowAllTrustedApps: Enabled
    Versions:
      - 10.0.18362.0
      - 10.0.19041.0
      - 10.0.22621.0
IDEs:
  Android Studio: Not Found
  Visual Studio:
    - 17.10.35027.167 (Visual Studio Enterprise 2022)
Languages:
  Java: Not Found
  Ruby: Not Found
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.73.7
    wanted: 0.73.7
  react-native-windows:
    installed: 0.73.11
    wanted: 0.73.11
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: Not found
  newArchEnabled: Not found
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found


React Native 74 Default App
System:
  OS: Windows 11 10.0.22631
  CPU: (24) x64 13th Gen Intel(R) Core(TM) i7-13700K
  Memory: 35.69 GB / 63.70 GB
Binaries:
  Node:
    version: 20.15.1
    path: C:\Program Files\nodejs\node.EXE
  Yarn:
    version: 3.6.4
    path: C:\Program Files (x86)\Yarn\bin\yarn.CMD
  npm:
    version: 10.7.0
    path: C:\Program Files\nodejs\npm.CMD
  Watchman: Not Found
SDKs:
  Android SDK: Not Found
  Windows SDK:
    AllowDevelopmentWithoutDevLicense: Enabled
    AllowAllTrustedApps: Enabled
    Versions:
      - 10.0.18362.0
      - 10.0.19041.0
      - 10.0.22621.0
IDEs:
  Android Studio: Not Found
  Visual Studio:
    - 17.10.35027.167 (Visual Studio Enterprise 2022)
Languages:
  Java: Not Found
  Ruby: Not Found
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.2
    wanted: 0.74.2
  react-native-windows:
    installed: 0.74.9
    wanted: 0.74.9
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found
Community Modules

No response

Target Platform Version

None

Target Device(s)

Desktop

Visual Studio Version

Visual Studio 2022

Build Configuration

Release

Snack, code example, screenshot, or link to a repository

The white box is where the content is positioned without a transform, the red box is where they are supposed to be after the transform is applied.

export function AnimationExampleSimple() {
  const transformYValueJS = useAnimatedValue(100);
  const transformYValueComposite = useAnimatedValue(100, {
    useNativeDriver: true,
  });

  return (
    <View
      style={[
        StyleSheet.absoluteFill,
        {justifyContent: 'center', alignItems: 'center'},
      ]}>
      <View
        style={{
          flexDirection: 'row',
          height: 100,
          width: 210,
          justifyContent: 'space-between',
          borderWidth: 2,
          borderColor: 'white',
        }}>
        <Animated.View
          style={{
            transform: [{translateY: transformYValueJS}],
            width: 100,
            height: 100,
            backgroundColor: 'green',
          }}
        />
        <Animated.View
          style={{
            transform: [{translateY: transformYValueComposite}],
            width: 100,
            height: 100,
            backgroundColor: 'blue',
          }}
        />
      </View>
      <View
        style={{height: 100, width: 210, borderWidth: 2, borderColor: 'red'}}
      />
    </View>
  );
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.