react-native-pager-view icon indicating copy to clipboard operation
react-native-pager-view copied to clipboard

Pager view causing crash in the app for some users in production

Open fawadmahmoodwashmen opened this issue 7 months ago • 12 comments

Environment

iOS 18.4.1 react native 0.78.2 react-native-pager-view 6.7.1

Description

Hello, We are experiencing issue with our production app where Sentry reporting crashes for some users, it is happening a few events each day & we are having tough time understanding the root cause. Can you please help us on what may have causing this?

EXC_BAD_ACCESS Exception 1, Code 1, Subcode 0 > Attempted to dereference null pointer.

Reproducible Demo

  • It happens randomly & has no specific scenario I can share so far, in some devices & some sessions the application crashes. I will post a complete Sentry stack-trace with in this thread.

Image

fawadmahmoodwashmen avatar May 18 '25 13:05 fawadmahmoodwashmen

Getting this in production as well, same exact stack trace. Did you find a fix? It happens when unmounting the pager view

alex-gale avatar Jun 04 '25 16:06 alex-gale

Should be fixed in 6.8.1

MrRefactor avatar Jun 13 '25 07:06 MrRefactor

Doesn't seem to be fixed for me in 6.8.1

mikebouwmans avatar Jun 19 '25 11:06 mikebouwmans

@mikebouwmans @alex-gale @MrRefactor Hello, anybody struggling with this issue please try this patch, this solved the issue for me in an production app.

react-native-pager-view+6.8.0.patch

fawadmahmoodwashmen avatar Jun 19 '25 11:06 fawadmahmoodwashmen

@fawadmahmoodwashmen that's quite a big patch so not able to test it.

mikebouwmans avatar Jul 02 '25 11:07 mikebouwmans

Hi @fawadmahmoodwashmen , I’ve identified the culprit: the issue occurs when the pager view is still scrolling during unmounting. @MrRefactor , please let me know if you need any additional details to work on a fix.

mikebouwmans avatar Jul 03 '25 07:07 mikebouwmans

Hi @fawadmahmoodwashmen , I’ve identified the culprit: the issue occurs when the pager view is still scrolling during unmounting. @MrRefactor , please let me know if you need any additional details to work on a fix.

Are you able to reproduce that in example app?

MrRefactor avatar Jul 03 '25 18:07 MrRefactor

What is the status of this issue?

rohit9625 avatar Jul 16 '25 07:07 rohit9625

@rohit9625 still exists react-native-pager-view@^6.8.1: version "6.8.1" think it related to https://github.com/callstack/react-native-pager-view/issues/458

bestofaIl avatar Jul 17 '25 15:07 bestofaIl

How we are supposed to fix this issue? I think it should be handled in the upstream.

rohit9625 avatar Jul 17 '25 18:07 rohit9625

same issue,only crash for production

Dokome avatar Jul 24 '25 02:07 Dokome

Got something similar on my end. Upgrading to 7.0.2 (the latest version at the moment) did not help in my case, but upgrading to 7.0.2 and applying this patch to did the trick, it seems.

diff --git a/ios/RNCPagerViewComponentView.mm b/ios/RNCPagerViewComponentView.mm
index cc0a1fa8e98f9ed4dca2b3ee9c6c320d72a25e7d..20fdde270dd404050234d34c9aaf9a35deeae538 100644
--- a/ios/RNCPagerViewComponentView.mm
+++ b/ios/RNCPagerViewComponentView.mm
@@ -127,6 +127,7 @@ using namespace facebook::react;
 
 
 -(void)prepareForRecycle {
+    scrollView.delegate = nil;
     [super prepareForRecycle];
     _nativePageViewController = nil;
     _currentIndex = -1;

I was not able to reliably reproduce this bug locally, but this synthetic test screen helped:

import { useCallback, useEffect, useRef, useState } from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';

import PagerView from 'react-native-pager-view';

export default function PagerStressTestScreen() {
  const [isRunning, setIsRunning] = useState(false);
  const [showPager, setShowPager] = useState(true);
  const [cycleCount, setCycleCount] = useState(0);

  const pagerRef = useRef<PagerView>(null);
  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const pageIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const onStartStressTest = useCallback(() => {
    setIsRunning(true);
    setCycleCount(0);

    intervalRef.current = setInterval(() => {
      setShowPager(prev => !prev);
      setCycleCount(c => c + 1);
    }, 150);

    pageIntervalRef.current = setInterval(() => {
      if (pagerRef.current) {
        const randomPage = Math.floor(Math.random() * 5);
        pagerRef.current.setPage(randomPage);
      }
    }, 50);
  }, []);

  const onStopStressTest = useCallback(() => {
    setIsRunning(false);
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
    if (pageIntervalRef.current) {
      clearInterval(pageIntervalRef.current);
      pageIntervalRef.current = null;
    }
  }, []);

  useEffect(() => {
    return () => {
      onStopStressTest();
    };
  }, [onStopStressTest]);

  return (
    <View style={styles.container}>
      <Text style={styles.cycles}>
        Cycles:
        {cycleCount}
      </Text>

      <View style={styles.buttons}>
        <Button disabled={isRunning} title="Start" onPress={onStartStressTest} />
        <Button disabled={!isRunning} title="Stop" onPress={onStopStressTest} />
      </View>

      {showPager ? (
        <PagerView ref={pagerRef} initialPage={0} style={styles.pager}>
          {[0, 1, 2, 3, 4].map(i => (
            <View key={i} style={styles.page}>
              <Text style={styles.pageText}>
                Page
                {i + 1}
              </Text>
            </View>
          ))}
        </PagerView>
      ) : (
        <View style={styles.placeholder}>
          <Text>Pager unmounted</Text>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
  },
  cycles: {
    fontSize: 16,
    marginBottom: 8,
  },
  buttons: {
    flexDirection: 'row',
    gap: 12,
    marginBottom: 16,
  },
  pager: {
    flex: 1,
    backgroundColor: 'white',
  },
  page: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  pageText: {
    fontSize: 32,
    fontWeight: 'bold',
  },
  placeholder: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'white',
  },
});

Hope this helps someone.

vshkl avatar Dec 03 '25 21:12 vshkl