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.

[V4] Dynamic Snap points not working with React Navigation

See original GitHub issue

Bug

Environment info

Library Version
@gorhom/bottom-sheet 4.0.0-alpha.30
react-native expo sdk-42.0.0
react-native-reanimated 2.2.0
react-native-gesture-handler 1.10.2
react-native-gesture-handler 1.10.2
@react-navigation/drawer 6.1.0
@react-navigation/native 6.0.2
@react-navigation/native-stack 6.1.0
@react-navigation/stack 6.0.3

Steps To Reproduce

Example Snack: https://snack.expo.dev/@thebiltheory/bottom-sheet-v4-with-react-navigation

  1. Implement dynamic snap points example
  2. Implement a navigator

Describe what you expected to happen:

  1. For the bottom sheet to dynamically take an appropriate height based on the content in each screen.
  2. For the bottom sheet to have a minimum height while a “loader” is being shown

Reproducible sample code

Example Snack: https://snack.expo.dev/@thebiltheory/bottom-sheet-v4-with-react-navigation

  const {
    animatedHandleHeight,
    animatedSnapPoints,
    animatedContentHeight,
    handleContentLayout,
  } = useBottomSheetDynamicSnapPoints(["CONTENT_HEIGHT"]);


<NativeViewGestureHandler disallowInterruption={true}>
      <View flex={1}>
        <BottomSheetModal
          name="Select"
          ref={newBookingModal.ref}
          onDismiss={resetCarForm}
          snapPoints={animatedSnapPoints}
          handleHeight={animatedHandleHeight}
          contentHeight={animatedContentHeight}
          enablePanDownToClose={true}
          keyboardBehavior="interactive"
          android_keyboardInputMode="adjustPan"
        >
          <BottomSheetScrollView
            onLayout={handleContentLayout}
            style={{
              flex: 1,
              backgroundColor: "red",
            }}
          >
            <NewBookingNavigator />
          </BottomSheetScrollView>
        </BottomSheetModal>
      </View>
    </NativeViewGestureHandler>

NewBookingNavigator.ts

 <NavigationContainer independent={true}>
      <Stack.Navigator
        screenOptions={screenOptions}
        initialRouteName="ScreenOne"
      >
        <Stack.Screen
          name="ScreenOne"
          options={{ title: "Screen One", headerShown: false }}
          component={ScreenOne}
        />
        <Stack.Screen
          name="ScreenTwo"
          options={{ title: "Screen Two", headerShown: false }}
          component={ScreenTwo}
        />
        ...
      </Stack.Navigator>
    </NavigationContainer>

_Originally posted by @thebiltheory in https://github.com/gorhom/react-native-bottom-sheet/discussions/427#discussioncomment-1158471_

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:6
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
gorhomcommented, Aug 25, 2021

try this

import React, { useCallback, useMemo, useRef } from "react";
import { StyleSheet, Text, View, Button } from "react-native";
import BottomSheet, {
  BottomSheetDraggableView,
  useBottomSheetDynamicSnapPoints,
} from "@gorhom/bottom-sheet";
import {
  NavigationContainer,
  useFocusEffect,
  useNavigation,
} from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { useAnimatedStyle } from "react-native-reanimated";

const Stack = createStackNavigator();

const ScreenA = ({ animatedContentHeight }) => {
  const { navigate } = useNavigation();
  const isFocus = useRef(false);
  const contentHeight = useRef(0);

  const handleContentLayout = useCallback(
    ({
      nativeEvent: {
        layout: { height },
      },
    }) => {
      if (isFocus.current) {
        contentHeight.current = height;
        animatedContentHeight.value = height;
      }
    },
    [animatedContentHeight]
  );

  useFocusEffect(() => {
    isFocus.current = true;
    animatedContentHeight.value = contentHeight.current;
    return () => {
      isFocus.current = false;
    };
  });
  return (
    <View onLayout={handleContentLayout}>
      <View style={[{ height: 400 }, styles.dummyScreen]}>
        <Text>Screen A</Text>
        <Button
          title="navigate to Screen B"
          onPress={() => navigate("ScreenB")}
        />
      </View>
    </View>
  );
};

const ScreenB = ({ animatedContentHeight }) => {
  const isFocus = useRef(false);
  const contentHeight = useRef(0);

  const handleContentLayout = useCallback(
    ({
      nativeEvent: {
        layout: { height },
      },
    }) => {
      if (isFocus.current) {
        contentHeight.current = height;
        animatedContentHeight.value = height;
      }
    },
    [animatedContentHeight]
  );

  useFocusEffect(() => {
    isFocus.current = true;
    animatedContentHeight.value = contentHeight.current;
    return () => {
      isFocus.current = false;
    };
  });
  return (
    <View onLayout={handleContentLayout}>
      <View style={[{ height: 200 }, styles.dummyScreen]}>
        <Text>Screen B</Text>
      </View>
    </View>
  );
};

const App = () => {
  const initialSnapPoints = useMemo(() => [100, "CONTENT_HEIGHT"], []);
  const {
    animatedContentHeight,
    animatedHandleHeight,
    animatedSnapPoints,
    handleContentLayout,
  } = useBottomSheetDynamicSnapPoints(initialSnapPoints);

  const sheetContentAnimatedStyle = useAnimatedStyle(
    () => ({
      minHeight:
        animatedContentHeight.value === 0 ? 200 : animatedContentHeight.value,
    }),
    [animatedContentHeight]
  );
  return (
    <View style={styles.container}>
      <BottomSheet
        handleHeight={animatedHandleHeight}
        contentHeight={animatedContentHeight}
        snapPoints={animatedSnapPoints}
      >
        <BottomSheetDraggableView style={sheetContentAnimatedStyle}>
          <NavigationContainer>
            <Stack.Navigator
              screenOptions={{
                headerShown: false,
                cardStyle: { backgroundColor: "white" },
              }}
            >
              <Stack.Screen name="ScreenA">
                {() => (
                  <ScreenA animatedContentHeight={animatedContentHeight} />
                )}
              </Stack.Screen>
              <Stack.Screen name="ScreenB">
                {() => (
                  <ScreenB animatedContentHeight={animatedContentHeight} />
                )}
              </Stack.Screen>
            </Stack.Navigator>
          </NavigationContainer>
        </BottomSheetDraggableView>
      </BottomSheet>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#333",
  },
  sheetContent: {
    minHeight: 1,
  },
  dummyScreen: {
    alignItems: "center",
    justifyContent: "center",
  },
});

export default App;
2reactions
github-actions[bot]commented, Aug 23, 2021

@thebiltheory: hello! 👋

This issue is being automatically closed because it does not follow the issue template.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Troubleshooting | React Navigation
Troubleshooting. This section attempts to outline issues that users frequently encounter when first getting accustomed to using React Navigation.
Read more >
Programmatically navigate using React router - Stack Overflow
With v4 of React Router, there are three approaches that you can take to programmatic routing within components. Use the withRouter higher-order ...
Read more >
Props | React Native Bottom Sheet - GitHub Pages
Content height helps dynamic snap points calculation. type, default, required. number | Animated.SharedValue<number>, undefined, NO. containerOffset ​.
Read more >
React Native carousel with react-native-snap-carousel
It has been fixed. Install “react-native-snap-carousel”: “^4.0.0-beta.6”. Version 3.6 is causing the issue.
Read more >
React Native scrollToIndex - Dynamic size item scroll inside ...
In this video tutorial you will learn about React Native scrollToIndex and how to scroll to an item inside a FlatList, ListView, ScrollView, ......
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