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

Modal blinking on different screens with previous content #2544

Closed
denysoleksiienko opened this issue Nov 29, 2024 · 4 comments
Closed

Modal blinking on different screens with previous content #2544

denysoleksiienko opened this issue Nov 29, 2024 · 4 comments
Labels
Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided

Comments

@denysoleksiienko
Copy link

Description

I created a simple dropdown menu using a native modal, but for some reason after closing it, the content of the previous modal appears in a blinking on the next screen where the dropdown menu using another content

Screen.Recording.2024-11-29.at.14.05.35.mov

Steps to reproduce

  • run yarn
  • run yarn pod-install
  • run yarn start
  • run yarn ios
  • open menu on home screen
  • open menu on profile screen
  • you will see the blinking previous modal

Snack or a link to a repository

https://github.com/denysoleksiienko/react-native-modal-blinking

Screens version

^4.3.0

React Native version

0.76.3

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

No response

Acknowledgements

Yes

@github-actions github-actions bot added Repro provided A reproduction with a snack or repo is provided Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS labels Nov 29, 2024
@denysoleksiienko
Copy link
Author

denysoleksiienko commented Nov 29, 2024

resolved by adding:

if (!visible && !position) {
  return null;
}

@TonyFTannous-Byd
Copy link

TonyFTannous-Byd commented Jan 10, 2025

same issue for me. but why before this version 4.0.0 we dont need to set this condition
it be enough to do that:
if (visible) {
<Modal ..../>
}

without else { return null }

Note: with else { return null } did not work, still the same blinking

react native 0.76.5, react-native-screens 4.5.0

@Jpoliachik
Copy link

I'm still experiencing this too
"react-native": "0.76.7",
"react-native-screens": "4.4.0",

this issue should be reopened IMO

@fbeaulieu
Copy link

fbeaulieu commented Feb 22, 2025

@Jpoliachik

I got the same issue using react-native 0.76.6 (on Ios) and I finally figured out a way out of it. Apparently, React Native modal keeps itself "alive" in some way (well it's a modal/portal kind of) and if seems to "retain" its previous content which displays "in between" the visibility transition.

In case it can help anyone, I just put together a simple OverlayContainer (which uses Modal), that clear it's content prior to "close" itself, so next time it reopen, there is just NO previous content.

(note my version also displays a Pressable container which is behind the content to be displayed for me to be able to close the modal whenever user press outside of the "Content" view.

OverlayContainer.tsx

import { Modal, Pressable, View } from 'react-native';
import React, { useEffect } from 'react';

export interface IOverlayContainerProps {
  children: React.ReactNode;
  visible: boolean;
  onPressOutsideContent?: () => void;
}

export const OverlayContainer = ({ children, visible, onPressOutsideContent }: IOverlayContainerProps) => {
  const [modalVisible, setModalVisible] = React.useState(visible);
  const [contentVisible, setContentVisible] = React.useState(visible);

  // This "patch" is a workaround to the RN Modal issue
  // where it flashes the previous content upon closing.
  // The trick is that whenever the Modal is set to VISIBLE FALSE,
  // it must first hide its content to flush it from Modal internal
  // memory, and then close the Modal itself, so the next time it 
  // become visible, it will not show any previous content
  // since it's been flushed the last time it was closed. It's kind
  // of a 2-step "make it invisible" process...
  useEffect(() => {
    // Closed by the parent...
    if (!visible) {
      setContentVisible(false);
    }
    else {
      setModalVisible(true);
      setContentVisible(true);
    }
  }, [visible]);

  // Since content visibility is controlled by THIS container,
  // we need to explicitly close the modal when the content is hidden.
  useEffect(() => {
    // Closed by the parent...
    if (!contentVisible && !visible) {
      setModalVisible(false);
    }
  }, [contentVisible]);

  return (
    <Modal transparent={true} visible={modalVisible} onRequestClose={onPressOutsideContent}>
      {contentVisible && (
        // FULLSCREEN CONTAINER VIEW WITH SCREEN CENTER {children}
        <View
          style={{
            height: '100%',
            width: '100%',
            zIndex: 98,
            justifyContent: 'center',
            alignItems: 'center',
          }}
        >
          {/* OVERLAY CONTENT */}
          {children}

          {/* PRESS OUTSIDE HANDLER */}
          <Pressable
            style={{
              position: 'absolute',
              height: '100%',
              width: '100%',
              backgroundColor: 'black',
              opacity: 0.2,
              zIndex: 95, // Meant to be lower than the content's
              borderRadius: 5,
              borderWidth: 0.25,
              borderColor: 'gray',
              justifyContent: 'center',
              alignItems: 'center',
            }}
            onPress={() => {
              onPressOutsideContent?.();
            }}
          />
        </View>
      )}
    </Modal>
  )
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided
Projects
None yet
Development

No branches or pull requests

4 participants