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 doesn't dismiss on iOS if LayoutAnimation queued beforehand #33733

Closed
vincentjames501 opened this issue Apr 28, 2022 · 12 comments
Closed
Labels
API: LayoutAnimation Component: Modal Impact: Bug The issue represents a bug somewhere Platform: iOS iOS applications. Priority: Low Stale There has been a lack of activity on this issue and it may be closed soon. Tech: React Native Core Issue related to the Core of React Native Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)

Comments

@vincentjames501
Copy link

Description

This appears to have broken during the 0.65.2 -> 0.66.0 release and is still broken in 0.68.1+.

We tend to use modals/overlays to indicate progress (such as deleting rows from tables) after which we want to schedule a layout animation and then close the modal. Below is a minimal program to reproduce and a gif showing the issue (you'll notice the modal pops back up even though it's not supposed to be visible and modalVisible is false!).

This behavior can be worked around by waiting for the animation to complete before closing the modal but in our case this is very tricky and couples the components too much together in our case.

Simulator.Screen.Recording.-.iPhone.13.-.2022-04-28.at.12.20.40.mp4
import React, { useState, useCallback } from "react";
import { Modal, StyleSheet, Text, Pressable, View, LayoutAnimation } from "react-native";

const App = () => {
  const [modalVisible, setModalVisible] = useState(false);
  const [count, setCount] = useState(0);
  const dismiss = useCallback(() => {
    LayoutAnimation.easeInEaseOut();
    setCount(c => c + 1);
    setModalVisible(false);
  }, [setCount, setModalVisible]);
  return (
    <View style={styles.centeredView}>
      <Modal
        animationType="slide"
        transparent={true}
        visible={modalVisible}
      >
        <View style={styles.centeredView}>
          <View style={styles.modalView}>
            <Text style={styles.modalText}>Hello World!</Text>
            <Pressable
              style={[styles.button, styles.buttonClose]}
              onPress={dismiss}
            >
              <Text style={styles.textStyle}>Hide Modal</Text>
            </Pressable>
          </View>
        </View>
      </Modal>
      <Pressable
        style={[styles.button, styles.buttonOpen]}
        onPress={() => setModalVisible(true)}
      >
        <Text style={styles.textStyle}>Show Modal</Text>
      </Pressable>
      <Text>{`Current count ${count}`}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  centeredView: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    marginTop: 22
  },
  modalView: {
    margin: 20,
    backgroundColor: "white",
    borderRadius: 20,
    padding: 35,
    alignItems: "center",
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2
    },
    shadowOpacity: 0.25,
    shadowRadius: 4,
    elevation: 5
  },
  button: {
    borderRadius: 20,
    padding: 10,
    elevation: 2
  },
  buttonOpen: {
    backgroundColor: "#F194FF",
  },
  buttonClose: {
    backgroundColor: "#2196F3",
  },
  textStyle: {
    color: "white",
    fontWeight: "bold",
    textAlign: "center"
  },
  modalText: {
    marginBottom: 15,
    textAlign: "center"
  }
});

export default App;

Version

0.68.1

Output of npx react-native info

$ npx react-native info 12:10:34
info Fetching system and libraries information...
System:
OS: macOS 12.3
CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
Memory: 65.53 MB / 32.00 GB
Shell: 3.4.1 - /usr/local/bin/fish
Binaries:
Node: 18.0.0 - /usr/local/bin/node
Yarn: 1.22.18 - /usr/local/bin/yarn
npm: 8.6.0 - /usr/local/bin/npm
Watchman: 2022.03.21.00 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.11.2 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.4, iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5
Android SDK:
API Levels: 28, 29, 30, 31
Build Tools: 28.0.3, 29.0.0, 29.0.2, 30.0.2, 31.0.0
System Images: android-29 | Google APIs Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 2020.3 AI-203.7717.56.2031.7935034
Xcode: 13.3.1/13E500a - /usr/bin/xcodebuild
Languages:
Java: 17.0.3 - /Users/vincent.pizzo/.jenv/shims/javac
npmPackages:
@react-native-community/cli: Not Found
react: 17.0.2 => 17.0.2
react-native: 0.68.1 => 0.68.1
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

Queue an animation, perform your state change followed by a request to close the modal.

Snack, code example, screenshot, or link to a repository

Simulator.Screen.Recording.-.iPhone.13.-.2022-04-28.at.12.20.40.mp4
@hetanthakkar
Copy link
Contributor

@vincentjames501 The issue seems legit, I will work on this issue

@hetanthakkar
Copy link
Contributor

@vincentjames501 I tried to reproduce your issue in this snack https://snack.expo.dev/@hetanthakkar/93dce1
I tried running it on ios emulator and I couldn’t reproduce the bug.

@vincentjames501
Copy link
Author

@hetanthakkar1 , I also couldn't reproduce it in the snack as my original plan was to post that but we 100% can on the iOS simulator and real devices on 0.68.1. Are you using expo locally by chance? I made a starter project with this.

npx react-native init BrokenLayoutAnimation
cd "./BrokenLayoutAnimation" && npx react-native run-ios

@vincentjames501
Copy link
Author

@hetanthakkar
Copy link
Contributor

@vincentjames501 yes you are right

@mokshmodi96
Copy link

@hetanthakkar1 @vincentjames501 any work around for this RN i am facing the same issue

@ivan114
Copy link

ivan114 commented May 15, 2022

for now i force the modal to close after animation, seem works for me

// ...
  useEffect(() => {
    if (visible) {
      setRealVisible(true);
    } else {
      // workaround for ios bug where modal not closing during layout animation
      requestAnimationFrame(() => {
        setRealVisible(false);
      });
    }
  }, [visible]);

  return (
    <Modal
      transparent={true}
      animationType="fade"
      statusBarTranslucent
      visible={realVisible}
      {...modelProps}
    >
// ...

@mokshmodi96
Copy link

Thank you @ivan114 you workaround worked for me!🚀

@cipolleschi cipolleschi added Priority: Low Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules) Tech: React Native Core Issue related to the Core of React Native Impact: Bug The issue represents a bug somewhere and removed Needs: Triage 🔍 labels May 18, 2022
@Ymjir
Copy link

Ymjir commented May 19, 2022

The problem is with animation, changing animationType="fade" to animationType="none" fixed the issue for me.

@github-actions
Copy link

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Nov 25, 2022
@github-actions
Copy link

github-actions bot commented Dec 3, 2022

This issue was closed because it has been stalled for 7 days with no activity.

@github-actions github-actions bot closed this as completed Dec 3, 2022
@vincentjames501
Copy link
Author

Still an issue

@facebook facebook locked as resolved and limited conversation to collaborators Dec 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
API: LayoutAnimation Component: Modal Impact: Bug The issue represents a bug somewhere Platform: iOS iOS applications. Priority: Low Stale There has been a lack of activity on this issue and it may be closed soon. Tech: React Native Core Issue related to the Core of React Native Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)
Projects
None yet
Development

No branches or pull requests

7 participants