Search code examples
reactjsreact-nativereact-hooksreact-native-reanimatedreact-native-reanimated-v2

What is the proper way to animate an array of objects with react-native-reanimated, considering a sub-component is not an option?


I am trying to use the react-native-reanimated v2 to animate an array of Animated.Views.

For my case, there are 2 handicaps:

  1. The objects will eventually animate each other. Because of this I am not able to generate a new sub-component for each draggable object. (If I try to do so, signaling between sub-components probably will be a hell.)
  2. The Rules of Hooks forbids the usage of the hooks within loops or other functions. (But that is what I need as far as I see.)

I made a snack to give the idea about what I try to achieve here (please note, one of the boxes is able to move another one here): https://snack.expo.dev/@mehmetkaplan/react-native-reanimated-array-animation

But I guess because of the above item 2, the snack does not behave consistent, sometimes the drag does not respond. (The single box version of the snack has a much more smooth response.)

Coming back to the main question. What is the proper way to animate an array of objects with react-native-reanimated, considering a sub-component is not an option?

Any suggestion is appreciated.


Solution

  • Using hooks in loop

    Definitely not something to be proud of but it'll be all right as long as the order of use... calls remains unaffected and all logic happens after the calls. This means during the lifecycle of the component, the number of iterations in the loop should not change.

    Basically the order in which all hooks are called should always be the same.

    Inconsistent behaviour

    Make sure your PanGestureHandler wraps Animated.View component otherwise it'll not work on mobile devices.

    Apart from weird drag handle (only working from Text) and breaking on mobile devices. I couldn't spot any inconsistency in the behaviour. Nesting the whole Animated.View inside PanGestureHandler fixes both issues,

    <PanGestureHandler onGestureEvent={gestureHandlers[i]}>
      <Animated.View style={[styles.box, animatedStyles[i]]} key={`View-${i}`}>
          <Text style={{color: "#FFFF00", fontWeight:'bold'}}>{`I am the box #${i}\nDrag Me${i === 1 ? "(I move also Box 0)" : ""}`}</Text>
      </Animated.View>
    </PanGestureHandler>
    

    Here is a working example,

    https://snack.expo.dev/A9IF7ngoC