wix / react-native-navigation

A complete native navigation solution for React Native
https://wix.github.io/react-native-navigation/
MIT License
13.04k stars 2.67k forks source link

componentDidAppear not fired after dismissing modal #5744

Closed idanlo closed 4 years ago

idanlo commented 4 years ago

Issue Description

we have a global componentDidAppear listener to track the current componentId on the screen, and now that we have modals in our app, the functionality of the componentDidAppear event (not firing the event after dismissing modals) causes our app navigation to be very inconsistent and hard to predict.

There are already multiple issues about this which were closed by stale bot which is very frustrating. Just because issues are stale doesn't mean that they were solved, so when I run to this issue it is very frustrating to find out that there is the same issue from 9 months ago that was closed because of inactivity. The issues - #5467 #4882

Steps to Reproduce / Code Snippets / Screenshots

  1. create stack layout
  2. create global componentDidAppear listener and track componentId using some sort of state management
  3. show a modal
  4. dismiss modal
  5. try to push a new screen using the componentId from the store - there will be an error because the componentId is referring to the modal and not the latest screen on the stack

Environment

guyca commented 4 years ago

Hey @idanlo I'm not sure I understand the issue. Could you please fork the repo and push a branch with a reproduction? Or better yet, PR a failing e2e test.

guyca commented 4 years ago

@idanlo Any chance you're using pageSheet modal? If that's the case then the root is still visible while the page sheet modal is displayed - therefore appear and disappear event are not emitted for the root.

you can use modalDIsmissedListener

idanlo commented 4 years ago

@yogevbd @guyca is there a way to get the componentId of the screen under the modal that is dismissing? Would be much easier to implement with a global event listener.

Also another question I have - I have a global event listener for componentDidAppear for keeping componentId in a global store, but I also have custom topBar components which I guess act as screens and also trigger that event. Is there a way to make RNN ignore topBar custom components for events like componentDidAppear?

guyca commented 4 years ago

@idanlo Navigation exposes a set of events which I'm sure can help you solve this use case.

Perhaps you can keep track of the last componentId which appeared before a modal was displayed. Listen to both didAppear and showModal events.

nathantqn commented 4 years ago

Hi @idanlo, this is my current approach to track global componentID:

import React, {useState} from 'react';
import {
  useNavigationComponentDidAppear,
  useNavigationModalDismiss,
} from 'react-native-navigation-hooks';
import {SCREEN} from 'constants/navigator';

export const NavigationComponentIDContext = React.createContext({
  componentID: '',
});

const LIST_OF_SCREENS_WITH_MODAL = [SCREEN.sleepSessionDetails];

const NavigationComponentIDProvider = ({children}) => {
  const [componentID, setComponentID] = useState('');
  const [screenIDWithModal, setScreenIDWithModal] = useState('');

  useNavigationComponentDidAppear(({componentId, componentName}) => {
    if (LIST_OF_SCREENS_WITH_MODAL.includes(componentName)) {
      setScreenIDWithModal(componentId);
    }
    setComponentID(componentId);
  });

  useNavigationModalDismiss(() => {
    setComponentID(screenIDWithModal);
  });
  return (
    <NavigationComponentIDContext.Provider value={{componentID}}>
      {children}
    </NavigationComponentIDContext.Provider>
  );
};

export default NavigationComponentIDProvider;