react-native-reanimated: [iOS] Crash when scrolling and use scroll event to animate header component : *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Mouting block is expected to not be set'

Description

App crash on iOS when use Animated.ScrollView and some interpolation based on scroll event from that list.

Application Specific Information:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Mouting block is expected to not be set'
terminating with uncaught exception of type NSException
abort() called
CoreSimulator 732.18.6 - Device: iPhone 12 (********-****-****-****-************) - Runtime: iOS 14.4 (18D46) - DeviceType: iPhone 12
Application Specific Backtrace 1:
0 CoreFoundation 0x00007fff20421af6 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff20177e78 objc_exception_throw + 48
2 CoreFoundation 0x00007fff2042191f +[NSException raise:format:] + 0
3 Foundation 0x00007fff20771633 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 166
4 mobile 0x000000010c9f076b -[REANodesManager uiManager:performMountingWithBlock:] + 267
5 mobile 0x000000010cbbf8a1 -[RCTUIManagerObserverCoordinator uiManager:performMountingWithBlock:] + 561
6 mobile 0x000000010cbb920d -[RCTUIManager flushUIBlocksWithCompletion:] + 701
7 mobile 0x000000010cbb8ec9 -[RCTUIManager _layoutAndMount] + 905
8 mobile 0x000000010cbb8b34 -[RCTUIManager batchDidComplete] + 36
9 mobile 0x000000010c9efc09 -[RCTUIManager(SyncUpdates) runSyncUIUpdatesWithObserver:] + 265
10 mobile 0x000000010c9f0c90 __36-[REANodesManager performOperations]_block_invoke + 480
11 mobile 0x000000010cbc02e0 __RCTExecuteOnUIManagerQueue_block_invoke + 32
12 libdispatch.dylib 0x00007fff2010532f _dispatch_call_block_and_release + 12
13 libdispatch.dylib 0x00007fff20106508 _dispatch_client_callout + 8
14 libdispatch.dylib 0x00007fff2010c3f9 _dispatch_lane_serial_drain + 715
15 libdispatch.dylib 0x00007fff2010cf74 _dispatch_lane_invoke + 403
16 libdispatch.dylib 0x00007fff20117577 _dispatch_workloop_worker_thread + 782
17 libsystem_pthread.dylib 0x00007fff61167499 _pthread_wqthread + 314
18 libsystem_pthread.dylib 0x00007fff61166467 start_wqthread + 15

Please check below videos and code samples.

Expected behavior

When screen content height has a huge amount (1200px) the animation works perfectly fine:

Video: https://screencast-o-matic.com/watch/crfqYfVn9iu

Actual behavior & steps to reproduce

When screen content height has size adjusted to current content the animation crash app in debug mode. In production mode header flickering but app still works.

Video: https://screencast-o-matic.com/watch/crfqYjVn9jx

Source of error in reanimated source code: https://github.com/software-mansion/react-native-reanimated/blob/master/ios/REANodesManager.m#L221

Snack or minimal code example

1. Working example

a) Header component

const Header: FunctionComponent<HeaderProps> = ({
  scrollY,
  headerContent,
  headerLeftTopContent,
  theme = 'light',
}) => {
  const navigation = useNavigation();
  const animatedHeaderStyles = useAnimatedStyle(() => {
    const paddingVertical = interpolate(
      scrollY.value,
      [0, 300],
      [appTheme.spacings.xl, appTheme.spacings.s],
      Extrapolate.CLAMP
    );

    const height = interpolate(scrollY.value, [0, 300], [135, 55], Extrapolate.CLAMP);

    return {
      paddingVertical,
      height,
    };
  });

  const infoStyles = useAnimatedStyle(() => {
    const opacity = interpolate(scrollY.value, [0, 300], [1, 0], Extrapolate.CLAMP);

    return {
      opacity,
    };
  });

  const selectedTheme = themeMapper[theme];

  return (
    <View style={styles.wrapper}>
      <SafeAreaView style={[styles.container]}>
        <Animated.View style={[styles.header, animatedHeaderStyles]}>
          <View style={styles.iconsContainer}>
            {headerLeftTopContent || (
              <TouchableOpacity
                onPress={() => navigation.navigate('Profile')}
                style={[
                  styles.iconContainer,
                  { backgroundColor: selectedTheme.iconBackgroundColor },
                ]}
              >
                <Icon name="person-outline" style={styles.icon} fill={selectedTheme.iconColor} />
              </TouchableOpacity>
            )}
            <TouchableOpacity
              onPress={() => navigation.navigate('Profile')}
              style={[styles.iconContainer, { backgroundColor: selectedTheme.iconBackgroundColor }]}
            >
              <Icon name="bell-outline" style={styles.icon} fill={selectedTheme.iconColor} />
            </TouchableOpacity>
          </View>
          <Animated.View style={[styles.infoContainer, infoStyles]}>{headerContent}</Animated.View>
        </Animated.View>
      </SafeAreaView>
    </View>
  );
};

b) ScreenWrapper

const ScreenWrapper = ({
  children,
  headerContent,
  headerLeftTopContent,
  theme = 'light',
  contentBackgroundColor,
}) => {
  const scrollY = useSharedValue(0);
  const onScroll = useAnimatedScrollHandler({
    onScroll: ({ contentOffset: { y: value } }) => {
      scrollY.value = value;
    },
  });

  return (
    <View
      style={{
        flex: 1,
      }}
    >
    
      <Header scrollY={scrollY} />

      <Animated.ScrollView
        onScroll={onScroll}
        scrollEventThrottle={16}
        style={styles.container}
        showsVerticalScrollIndicator={false}
        contentContainerStyle={{
          backgroundColor: palette.white,
          borderTopLeftRadius: 32,
          borderTopRightRadius: 32,
        }}
      >
        <View style={{ zIndex: -1 }}>
          {children}
        </View>
      </Animated.ScrollView>
    </View>
  );
};

c) Screen

<ScreenWrapper>
  <View style={{ minHeight: 1200 }}>
    /* content */
  <View>
</ScreenWrapper>
    

2. Problematic code

Header and ScreenWrapper are the same, only Screen component doesn’t have set height to big amount

<ScreenWrapper>
  /* content */
</ScreenWrapper>

Package versions

  • React Native: 0.64.0 (JSC)
  • React Native Reanimated: 2.1.0
  • NodeJS: 12.16.1
  • Xcode: 12.4
  • Java & Gradle: -

Affected platforms

  • Android
  • iOS
  • Web

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 16
  • Comments: 15 (2 by maintainers)

Most upvoted comments

Same issue here: https://github.com/software-mansion/react-native-reanimated/issues/2285 I am working on this and I will notify you about progress.

Same here it is working if I set offsetY.value = withTiming(event.contentOffset.y, {duration: 10}); and will be crashed offsetY.value = event.contentOffset.y;

Hi, I had a similar issue and came to the understanding that the issue happens due to frequent height updates. No issue observed with the translation value. You can solve this simply by putting withTiming hook to animatedScrollHandler.

  const scrollHandler = useAnimatedScrollHandler((event) => {
      cancelAnimation(progress);
      progress.value = withTiming(
        interpolate(
          event.contentOffset.y,
          [0, 300],
          [0, 1],
          Extrapolate.CLAMP,
        ),
        { duration: 50 },
      );
  });

There will be a very small delay, but in my case, it was not crucial.

@wcastand With this little info it of course is hard to pinpoint the issue. Can you try expanding the height of the view you’re trying to scroll? I ran into some flickering issues when the view was the same height as the window as well. Kinda hacky, but resolved it with making the view larger 🤷‍♂️

hello everyone any news? I am also having this issue