React-native-reanimated: diffClamp conflict when used more than once?

Created on 27 Apr 2020  路  3Comments  路  Source: software-mansion/react-native-reanimated

Description

When I use diffClamp to operate on a single value the results are predictable.
Once a second instance of diffClamp is employed both values become unpredictable.

Screenshots

panTest

Steps To Reproduce

import React from "react";
import { Dimensions, SafeAreaView, StyleSheet, View } from "react-native";
import Animated, {
  Value,
  add,
  cond,
  diffClamp,
  eq,
  event,
  set,
} from "react-native-reanimated";
import { PanGestureHandler, State } from "react-native-gesture-handler";

const SCREEN = {
  height: Dimensions.get("screen").height,
  width: Dimensions.get("screen").width,
};

const BOUNDS = {
  x: {
    min: 0,
    max: SCREEN.width - 100,
  },
  y: {
    min: 0,
    max: SCREEN.height - 100,
  },
};

const PanTest = () => {
  const state = new Value(State.UNDETERMINED);
  const translationX = new Value(0);
  const translationY = new Value(0);

  const gestureHandler = event([
    {
      nativeEvent: {
        state,
        translationX,
        translationY,
      },
    },
  ]);

  const withOffset = (
    value: Animated.Node<number>,
    gestureState: Animated.Node<number>
  ): Animated.Node<number> => {
    const offset = new Value(0);
    return cond(
      eq(gestureState, State.END),
      [set(offset, add(offset, value)), offset],
      add(offset, value)
    );
  };

  const translateX = diffClamp(
    withOffset(translationX, state),
    BOUNDS.x.min,
    BOUNDS.x.max
  );

  const translateY = diffClamp(
    withOffset(translationY, state),
    BOUNDS.y.min,
    BOUNDS.y.max
  );

  return (
    <SafeAreaView>
      <View style={styles.container}>
        <PanGestureHandler
          onHandlerStateChange={gestureHandler}
          onGestureEvent={gestureHandler}
        >
          <Animated.View
            style={[
              styles.box,
              {
                transform: [{ translateX }, { translateY }],
              },
            ]}
          />
        </PanGestureHandler>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  box: {
    position: "absolute",
    width: 100,
    height: 100,
    backgroundColor: "red",
  },
});

export default PanTest;

Expected behavior

Values should remain independent, and within the bounds specified, regardless of how many instances of diffClamp are used

Actual behavior

Seemingly, multiple instances of diffClamp affect values in others.

Package versions

  • Expo: 37.0.0
  • React: 16.9.0
  • React Native: 0.61
  • React Native Reanimated: 1.7.0
  • React Native Gesture Handler: 1.6.0
馃悶 Bug

Most helpful comment

You can use Diffclamp from 'react-native-redash' which works exactly the same but doesn't have this problem.

All 3 comments

I saw this problem last week. I believe this is the same problem as outlined here:

https://github.com/software-mansion/react-native-reanimated/pull/746

From what I understand, diffClamp is a stateful animation operator that relies on the previous value of an internal variable in the library. Right now the library shares this variable among different instances, so we need to separate the diffClamp function per-instance.

You can use Diffclamp from 'react-native-redash' which works exactly the same but doesn't have this problem.

This is another instance of proc bug which shows up when you use set() on Value with nodes that are dependent of other Value.

Was this page helpful?
0 / 5 - 0 ratings