question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Draggable AnimatedViews crash simulator

See original GitHub issue

When running on iOS simulator, draggable AnimatedViews throw an unhandled error. I’ve already tested this in release on testflight, and the draggable modal behaves as expected with no error.

React Native version:

react: 16.8.3 => 16.8.3 react-native: 0.59.8 => 0.59.8

Steps To Reproduce

  1. Create an AnimatedView and a PanResponder which controls the position of the view
  2. Try and drag the View.

The View should drag according to the PanResponder, but instead errors out with the following error:

Invariant Violation: [2165,\"RCTView\",{\"top\":0,\"left\":\"<<NaN>>\",\"transform\":[{\"translateY\":40}]}] is not usable as a native method argument\n at invariant

-[RCTCxxBridge handleError:]
__34-[RCTCxxBridge _initializeBridge:]_block_invoke
facebook::react::RCTMessageThread::tryFunc(std::__1::function<void ()> const&)
facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1::operator()() const
decltype(std::__1::forward<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(fp)()) std::__1::__invoke<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&&&)
void std::__1::__invoke_void_return_wrapper<void>::__call<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&&&)
std::__1::__function::__func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()()
std::__1::function<void ()>::operator()() const
invocation function for block in facebook::react::RCTMessageThread::runAsync(std::__1::function<void ()>)
__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__
__CFRunLoopDoBlocks
__CFRunLoopRun
CFRunLoopRunSpecific
+[RCTCxxBridge runRunLoop]
__NSThread__start__
_pthread_body
_pthread_start
thread_start

You can reproduce it with the following, however, on snack, this does not crash I assume because Expo is a on their own fork?

import { View,
  Text,
  StyleSheet,
  TouchableOpacity,
  TouchableHighlight,
  PanResponder,
  Animated,
  Dimensions,
} from 'react-native';


const { height: SCREEN_HEIGHT } = Dimensions.get('window');
const SWIPE_THRESHOLD = SCREEN_HEIGHT * 0.1;

class ConfirmationModal extends Component {
  constructor(props) {
    super(props);
    const modalPosition = new Animated.ValueXY();
    const panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onPanResponderMove: (_event, gesture) => {
        if (gesture.dy > 0) {
          modalPosition.setValue({ y: gesture.dy });
        }
      },
      onPanResponderRelease: (_event, gesture) => {
        if (gesture.dy <= SWIPE_THRESHOLD) {
          Animated.spring(modalPosition, {
            toValue: {
              x: 0,
              y: 0,
            },
            bounciness: 12,
            speed: 8,
          }).start();
        }
        if (gesture.dy > SWIPE_THRESHOLD) {
          this.props.toggleModal();
        }
      },
    });
    this.state = {
      panResponder,
      modalPosition,
    }
  }

  getModalStyle() {
    const { modalPosition } = this.state;
    const drag = modalPosition.y.interpolate({
      inputRange: [0, SCREEN_HEIGHT],
      outputRange: [0, 250],
    });

    return {
      ...modalPosition.getLayout(),
      transform: [{ translateY: drag }],
    };
  }
  
  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity style={{ flex: 4, opacity: 0.2 }} onPress={this.props.toggleModal} activeOpacity={1} />
        <Animated.View style={[styles.contentContainer, this.getModalStyle()]}>
          <View style={styles.upperContainer}>
            <View style={styles.notch} {...this.state.panResponder.panHandlers} />
            <View style={styles.topRow}>
            </View>
            <View style={{ paddingHorizontal: 20, paddingTop: 5 }}>
            </View>
            <View style={{ paddingTop: 15, paddingHorizontal: 20, }}>
            </View>
          </View>
          <View style={styles.lowerContainer}>
            <TouchableOpacity onPress={this.props.toggleModal}>
              <Text style={styles.cancelText}>Cancel</Text>
            </TouchableOpacity>
            <TouchableHighlight>
              <View>
                <Text style={styles.confirmText}>Confirm</Text>
              </View>
            </TouchableHighlight>
          </View>
        </Animated.View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container:  {
    flex: 1,
  },
  contentContainer: {
    flex: 3,
    backgroundColor: 'rgb(64, 77, 222)',
    borderTopLeftRadius: 13,
    borderTopRightRadius: 13,
  },
  upperContainer: {
    flex: 3,
  },
  lowerContainer: {
    flex: 1,
    backgroundColor: 'rgb(58, 73, 192)',
    flexDirection: 'row',
    paddingHorizontal: 20,
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  notch: {
    height: 8,
    width: 48,
    backgroundColor: 'rgb(161, 182, 255)',
    alignSelf: 'center',
    marginTop: 5,
    borderRadius: 8,
    opacity: 0.85,
  },
  topRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingHorizontal: 20,
  },
  lowerRow: {
    backgroundColor: 'rgb(58, 73, 192)',
  },
  confirmTitle: {
    fontFamily: 'SFProText-Medium',
    fontSize: 18,
    color: 'rgb(146, 166, 249)',
  },
  confirmBodyText: {
    fontFamily: 'SFProText-Semibold',
    fontSize: 20,
    lineHeight: 28,
    letterSpacing: -0.3,
    color: 'rgb(199, 210, 255)',
  },
  confirmButton: {
    paddingHorizontal: 30,
    paddingVertical: 15,
    borderRadius: 25,
    justifyContent: 'center',
    alignItems: 'center',
  },
  cancelText: {
    fontFamily: 'SFProText-Medium',
    fontSize: 18,
    letterSpacing: 0.18,
    color: 'rgb(146, 166, 249)',
  },
  confirmText: {
    fontFamily: 'SFProText-Bold',
    fontSize: 18,
    letterSpacing: -0.6,
    color: 'rgb(26, 71, 114)',
  },
})

export default ConfirmationModal;

As I said, this is not occurring in our release builds, but obviously makes debugging a pain .

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:8

github_iconTop GitHub Comments

1reaction
chops318commented, Aug 7, 2019

@steventilator Correct, if you follow down to the Animated API level, you’ll see that x is evaluated as NaN if not supplied

1reaction
chops318commented, May 21, 2019

As a temporary workaround, when setting the modal position using an AnimatedValue with setValue, you must supply an x and y coordinates (lucky for me, my use case does not need anything but 0 as x).

By using this

      onPanResponderMove: (_event, gesture) => {
        if (gesture.dy > 0) {
          modalPosition.setValue({ x: 0 y: gesture.dy });
        }
      },

This fixes the issue on simulator. As a side note, the offending underlying API piece is essentially being passed NaN as a value, causing the error. Not sure what changes (or when) as we updated from 57 to 59. If I end up with free time I may dig into seeing when this changed (and maybe a contributor can tell us if the change is intended)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Practice with Path Animations | Part 1 - Virtual CRASH
The path animation tool is a great way to create fast visual aids for your case without the need to optimize a simulation...
Read more >
Drag and Drop Collision Detection Demo - Konva
In this demo we will use simple collision detection to highlight intersected objects. For simplicity we will use just bounding boxes to detect...
Read more >
Animations in React Native: Performance and Reason-about ...
The end result will be a custom slider, and a circular progress that animates as you drag the slider handle. The "Reanimated Mental...
Read more >
Collision Detection - Happy Coding
If you can determine that two shapes touch, you can trigger some action- think of detecting when the user has moused over a...
Read more >
Animated Drag and Drop with React Native - Modus Create
xcode file in xCode to build and run the project in the iOS simulator. Creating the views. Before we start coding, let's create...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found