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.

Modal reopens while dismissing if it gets re-rendered while closing

See original GitHub issue

Bug

This is a bit more precise version (with reproducible code sample) of #191.

If your handler call dismiss but also triggers the modal to get updated, then modal doesn’t get dismissed, it reopens.

https://user-images.githubusercontent.com/6768840/104815091-e1482c00-5855-11eb-9797-048efd23f69e.mov

Full repro is noted below (thought it only contains 1 line diff from the example app), and related screen code is as below.

import React, { useCallback, useMemo, useRef, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { BottomSheetModal, BottomSheetView } from '@gorhom/bottom-sheet';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Button from '../../components/button';
import withModalProvider from '../withModalProvider';

const DynamicSnapPointExample = () => {
  // state
  const [count, setCount] = useState(0);
  const [contentHeight, setContentHeight] = useState(0);

  // hooks
  const bottomSheetRef = useRef<BottomSheetModal>(null);
  const { bottom: safeBottomArea } = useSafeAreaInsets();

  // variables
  const snapPoints = useMemo(() => [contentHeight], [contentHeight]);

  // callbacks
  const handleIncreaseContentPress = useCallback(() => {
    setCount(state => state + 1);
  }, []);
  const handleDecreaseContentPress = useCallback(() => {
    setCount(state => Math.max(state - 1, 0));
  }, []);

  const handlePresentPress = useCallback(() => {
    bottomSheetRef.current?.present();
  }, []);
  const handleDismissPress = useCallback(() => {
    // NOTE: This setCount call triggers the issue
    setCount(state => state + 1);
    bottomSheetRef.current?.dismiss();
  }, []);
  const handleOnLayout = useCallback(
    ({
      nativeEvent: {
        layout: { height },
      },
    }) => {
      setContentHeight(height);
    },
    []
  );

  // styles
  const contentContainerStyle = useMemo(
    () => ({
      ...styles.contentContainerStyle,
      paddingBottom: safeBottomArea,
    }),
    [safeBottomArea]
  );
  const emojiContainerStyle = useMemo(
    () => ({
      ...styles.emojiContainer,
      height: 50 * count,
    }),
    [count]
  );

  // renders
  const renderBackground = useCallback(
    () => <View style={styles.background} />,
    []
  );

  return (
    <View style={styles.container}>
      <Button
        label="Present"
        style={styles.buttonContainer}
        onPress={handlePresentPress}
      />
      <Button
        label="Dismiss"
        style={styles.buttonContainer}
        onPress={handleDismissPress}
      />
      <BottomSheetModal
        ref={bottomSheetRef}
        index={0}
        snapPoints={snapPoints}
        backgroundComponent={renderBackground}
      >
        <BottomSheetView
          style={contentContainerStyle}
          onLayout={handleOnLayout}
        >
          <Text style={styles.message}>
            Could this sheet modal resize to its content height ?
          </Text>
          <View style={emojiContainerStyle}>
            <Text style={styles.emoji}>😍</Text>
          </View>
          <Button
            label="Yes"
            style={styles.buttonContainer}
            onPress={handleIncreaseContentPress}
          />
          <Button
            label="Maybe"
            style={styles.buttonContainer}
            onPress={handleDecreaseContentPress}
          />
        </BottomSheetView>
      </BottomSheetModal>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
  },
  background: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'white',
  },
  buttonContainer: {
    marginBottom: 6,
  },
  contentContainerStyle: {
    paddingTop: 12,
    paddingHorizontal: 24,
    backgroundColor: 'white',
  },
  message: {
    fontSize: 24,
    fontWeight: '600',
    marginBottom: 12,
  },
  emoji: {
    fontSize: 156,
    textAlign: 'center',
    alignSelf: 'center',
  },
  emojiContainer: {
    overflow: 'hidden',
    justifyContent: 'center',
  },
});

export default withModalProvider(DynamicSnapPointExample);

Environment info

Library Version
@gorhom/bottom-sheet 2.0.4
react-native 0.63.4
react-native-reanimated 1.13.2
react-native-gesture-handler 1.9.0

Steps To Reproduce

  1. Clone the repo below
  2. Run the example app and select MODAL > Dynamic Snap Point example
  3. Press Present
  4. Press Dismiss

Describe what you expected to happen:

  1. Modal closes without reopening

Reproducible sample code

https://github.com/heejongahn/react-native-bottom-sheet

You can verify this behavior with example/src/sceens/modal/DynamicSnapPointExample.tsx. (diff from original example)

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:20 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
oilladacommented, Aug 28, 2022

Same problem here using tab bar, when I navigate from the tab that have the bottom sheet (and its closed) and then comeback to the same tab, the bottom sheet appears open. The problem is only with Android.

2reactions
gorhomcommented, Jan 29, 2021

this should be fixed with v2.0.7 🎉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Prevent modal from closing after re-render in react
Something is obviously going very wrong here, the Modal should not close. As a workaround you could do something like this:
Read more >
Build a simple Modal Component with React - Bits and Pieces
This will render whatever is passed to this component, which is just perfect for a dynamic modal. Close the modal. After opening a...
Read more >
Build a complete Modal Component with React Hooks
If the user uses the ESCAP key on his keyboard, then the modal closes. The result is: React Modal close. The CSS !...
Read more >
Visualforce component as modal dialog - Salesforce Developers
When you are using reRender, you are rendering the content, so when you have "rendered" on the same level, it is not evaluated....
Read more >
<af:dialog> - Oracle Help Center
Server-side listeners can be registered with the parent af:popup component and will be invoked when the dialog is dismissed using a closed dialog...
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