Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gesture error when applying pagination #665

Open
bil-lekid opened this issue Sep 10, 2024 · 2 comments
Open

Gesture error when applying pagination #665

bil-lekid opened this issue Sep 10, 2024 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@bil-lekid
Copy link

bil-lekid commented Sep 10, 2024

Describe the bug
I copied the parallax horizontal code. It doesn't work but when I removed the pagination the carousel works. And I want to use the pagination

To Reproduce
Steps to reproduce the behavior:

  1. Copy the code
import * as React from "react";
import { Dimensions, Text, View } from "react-native";
import { useSharedValue } from "react-native-reanimated";
import Carousel, {
  ICarouselInstance,
  Pagination,
} from "react-native-reanimated-carousel";

const data = [...new Array(6).keys()];
const width = Dimensions.get("window").width;

function App() {
  const ref = React.useRef<ICarouselInstance>(null);
  const progress = useSharedValue<number>(0);
  
  const onPressPagination = (index: number) => {
    ref.current?.scrollTo({
      count: index - progress.value,
      animated: true,
    });
  };

  return (
    <View style={{ flex: 1 }}>
      <Carousel
        ref={ref}
        width={width}
        height={width / 2}
        data={data}
        onProgressChange={progress}
        renderItem={({ index }) => (
          <View
            style={{
              flex: 1,
              borderWidth: 1,
              justifyContent: "center",
            }}
          >
            <Text style={{ textAlign: "center", fontSize: 30 }}>{index}</Text>
          </View>
        )}
      />
      <Pagination.Basic
        progress={progress}
        data={data}
        dotStyle={{ backgroundColor: "rgba(0,0,0,0.2)", borderRadius: 50 }}
        containerStyle={{ gap: 5, marginTop: 10 }}
        onPress={onPressPagination}
      />
    </View>
  );
}

export default App;
  1. It will show this error
Error: NativeViewGestureHandler must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.

This error is located at:
    in NativeViewGestureHandler (created by RNGestureHandlerButton)
    in RNGestureHandlerButton (created by BaseButton)
    in BaseButton (created by GenericTouchable)
    in GenericTouchable
    in Unknown (created by Basic)
    in RCTView (created by View)
    in View (created by Basic)
    in Basic (created by App)
    in RCTView (created by View)
    in View (created by App)
    in App (created by AuthIndex)
    in RCTView (created by View)
    in View (created by ThemedView)
    in ThemedView (created by AuthIndex)
    in AuthIndex
    in Unknown (created by Route(index))
    in Suspense (created by Route(index))
    in Route (created by Route(index))
    in Route(index) (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RCTView (created by View)
    in View (created by SceneView)
    in RNSScreen (created by Animated(Anonymous))
    in Animated(Anonymous) (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)
    in RNSScreenStack (created by ScreenStack)
    in ScreenStack (created by NativeStackViewInner)
    in NativeStackViewInner (created by NativeStackView)
    in RCTView (created by View)
    in View (created by SafeAreaProviderCompat)
    in SafeAreaProviderCompat (created by NativeStackView)
    in NativeStackView (created by NativeStackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator
    in Unknown (created by AuthLayout)
    in RNCSafeAreaView
    in Unknown (created by AuthLayout)
    in AuthLayout
    in Unknown (created by Route(auth))
    in Suspense (created by Route(auth))
    in Route (created by Route(auth))
    in Route(auth) (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RCTView (created by View)
    in View (created by SceneView)
    in RNSScreen (created by Animated(Anonymous))
    in Animated(Anonymous) (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)
    in RNSScreenStack (created by ScreenStack)
    in ScreenStack (created by NativeStackViewInner)
    in NativeStackViewInner (created by NativeStackView)
    in RCTView (created by View)
    in View (created by SafeAreaProviderCompat)
    in SafeAreaProviderCompat (created by NativeStackView)
    in NativeStackView (created by NativeStackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator
    in Unknown (created by RootLayout)
    in ThemeProvider (created by RootLayout)
    in QueryClientProvider (created by RootLayout)
    in RootLayout
    in Unknown (created by Route())
    in Suspense (created by Route())
    in Route (created by Route())
    in Route() (created by ContextNavigator)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by wrapper)
    in wrapper (created by ContextNavigator)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by ContextNavigator)
    in ContextNavigator (created by ExpoRoot)
    in ExpoRoot (created by App)
    in App (created by ErrorOverlay)
    in ErrorToastContainer (created by ErrorOverlay)
    in ErrorOverlay (created by withDevTools(ErrorOverlay))
    in withDevTools(ErrorOverlay)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent), js engine: hermes
  1. Delete the <Pagination.Basic />
  2. Carousel works but pagination gone

Expected behavior
Both Carousel and Pagination working

Screenshots
If applicable, add screenshots to help explain your problem.

Versions (please complete the following information):
"expo": "~51.0.28",
"react": "18.2.0",
"react-native": "0.74.5",
"react-native-gesture-handler": "~2.16.1",
"react-native-reanimated": "~3.10.1",
"react-native-reanimated-carousel": "4.0.0-alpha.12",

Smartphone (please complete the following information):

  • Device: Samsung A71 [e.g. iPhone6]
  • OS: Android 13 [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

@bil-lekid bil-lekid added the bug Something isn't working label Sep 10, 2024
Copy link

dosubot bot commented Sep 10, 2024

Hey @bil-lekid! I'm here to help you with any bugs, questions, or contributions while you wait for a human maintainer. Let's get to the bottom of this together!

To resolve the "NativeViewGestureHandler must be used as a descendant of GestureHandlerRootView" error when using pagination with the react-native-reanimated-carousel, you need to ensure that the Carousel component is wrapped in a GestureHandlerRootView. This is necessary for the gesture handlers to work correctly.

Here's how you can modify your code to include the GestureHandlerRootView:

import * as React from "react";
import { View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { useSharedValue } from "react-native-reanimated";
import Carousel, {
  ICarouselInstance,
  Pagination,
} from "react-native-reanimated-carousel";

import { SBItem } from "../../components/SBItem";
import SButton from "../../components/SButton";
import { ElementsText, window } from "../../constants";

const PAGE_WIDTH = window.width;
const colors = [
  "#26292E",
  "#899F9C",
  "#B3C680",
  "#5C6265",
  "#F5D399",
  "#F1F1F1",
];

function Index() {
  const [isVertical, setIsVertical] = React.useState(false);
  const [autoPlay, setAutoPlay] = React.useState(false);
  const [pagingEnabled, setPagingEnabled] = React.useState<boolean>(true);
  const [snapEnabled, setSnapEnabled] = React.useState<boolean>(true);
  const progress = useSharedValue<number>(0);
  const baseOptions = isVertical
    ? ({
        vertical: true,
        width: PAGE_WIDTH * 0.86,
        height: PAGE_WIDTH * 0.6,
      } as const)
    : ({
        vertical: false,
        width: PAGE_WIDTH,
        height: PAGE_WIDTH * 0.6,
      } as const);

  const ref = React.useRef<ICarouselInstance>(null);

  const onPressPagination = (index: number) => {
    ref.current?.scrollTo({
      count: index - progress.value,
      animated: true,
    });
  };

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <View
        style={{
          alignItems: "center",
        }}
      >
        <Carousel
          ref={ref}
          {...baseOptions}
          style={{
            width: PAGE_WIDTH,
          }}
          loop
          pagingEnabled={pagingEnabled}
          snapEnabled={snapEnabled}
          autoPlay={autoPlay}
          autoPlayInterval={1500}
          onProgressChange={progress}
          mode="parallax"
          modeConfig={{
            parallaxScrollingScale: 0.9,
            parallaxScrollingOffset: 50,
          }}
          data={colors}
          renderItem={({ index }) => <SBItem index={index} />}
        />

        <Pagination.Basic
          progress={progress}
          data={colors}
          dotStyle={{ backgroundColor: "rgba(0,0,0,0.2)" }}
          containerStyle={{ gap: 5, marginBottom: 10 }}
          onPress={onPressPagination}
        />

        <Pagination.Basic<{ color: string }>
          progress={progress}
          data={colors.map((color) => ({ color }))}
          dotStyle={{
            width: 25,
            height: 4,
            backgroundColor: "rgba(0,0,0,0.2)",
          }}
          activeDotStyle={{
            overflow: "hidden",
          }}
          containerStyle={[
            isVertical
              ? {
                  position: "absolute",
                  width: 25,
                  right: 5,
                  top: 40,
                }
              : undefined,
            {
              gap: 10,
              marginBottom: 10,
            },
          ]}
          horizontal={!isVertical}
          onPress={onPressPagination}
        />

        <Pagination.Basic<{ color: string }>
          progress={progress}
          data={colors.map((color) => ({ color }))}
          size={20}
          dotStyle={{
            borderRadius: 100,
            backgroundColor: "rgba(0,0,0,0.2)",
          }}
          activeDotStyle={{
            borderRadius: 100,
            overflow: "hidden",
          }}
          containerStyle={[
            isVertical
              ? {
                  position: "absolute",
                  width: 20,
                  right: 5,
                  top: 40,
                }
              : undefined,
            {
              gap: 5,
              marginBottom: 10,
            },
          ]}
          horizontal={!isVertical}
          onPress={onPressPagination}
        />

        <Pagination.Basic<{ color: string }>
          progress={progress}
          data={colors.map((color) => ({ color }))}
          size={20}
          dotStyle={{
            borderRadius: 100,
            backgroundColor: "rgba(0,0,0,0.2)",
          }}
          activeDotStyle={{
            borderRadius: 100,
            overflow: "hidden",
          }}
          containerStyle={[
            isVertical
              ? {
                  position: "absolute",
                  width: 20,
                  right: 5,
                  top: 40,
                }
              : undefined,
          ]}
          horizontal={!isVertical}
          renderItem={(item) => (
            <View
              style={{
                backgroundColor: item.color,
                flex: 1,
              }}
            />
          )}
          onPress={onPressPagination}
        />

        <SButton
          onPress={() => setAutoPlay(!autoPlay)}
        >{`${ElementsText.AUTOPLAY}:${autoPlay}`}</SButton>
        <SButton
          onPress={() => {
            setIsVertical(!isVertical);
          }}
        >
          {isVertical ? "Set horizontal" : "Set Vertical"}
        </SButton>
        <SButton
          onPress={() => {
            setPagingEnabled(!pagingEnabled);
          }}
        >
          {`pagingEnabled:${pagingEnabled}`}
        </SButton>
        <SButton
          onPress={() => {
            setSnapEnabled(!snapEnabled);
          }}
        >
          {`snapEnabled:${snapEnabled}`}
        </SButton>
      </View>
    </GestureHandlerRootView>
  );
}

export default Index;

Make sure that the GestureHandlerRootView is the top-level component or at least wraps the Carousel component in your component tree. This should resolve the error [1].

To continue talking to Dosu, mention @dosu.

@traviswimer
Copy link

This bug seems to be fixed for me in v4.0.0-canary.17.

I think it may have been fixed with v4.0.0-canary.15.

The error also went away for me in 4.0.0-alpha.12 if I wrapped both the carousel and pagination components in another GestureHandlerRootView.

The docs for react-native-gesture-handler don't seem to mention anything about nesting multiple GestureHandlerRootView components (the Carousel component includes it). But since they do recommend including it in open-source libraries this way, I assume it is probably safe to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants