yesIamFaded
yesIamFaded

Reputation: 2068

ComponentWillUnmount is not getting called React-Navigation

I know this question already exists on Stack Overflow but most questions and answers are very old. I am working on an app that performs a fetch call to a db inside componentDidMount obviously using react-native.

I have an interval running in componentDidMount that calls a query and it works well. Now I need to call clearInterval(this.interval) inside componentWillUnmount to stop the query and logging in my app.

  1. It should be called when I press a save button and navigate with props.navigation.navigate("new Screen", {params})
    I read a solution for this where I should use props.navgiation.replace("Screen") - but it doesn't work for me

  2. The second important part is that componentWillUnmount also needs to be called when I press on another tab (using bottom-tab-navigator)

I understand that the screens in a stack navigator for example never really unmount. So is there a different way to call componentWillUnmount maybe something like when the user left screen( or loses focus on-screen) or user left the specific routeName or something.

My componentWillUnmount - really simple:

  componentWillUnmount(){
    clearInterval(this.interval)
    console.log("Component did Unmount")
  }

it's only called if I go to my LogOut Screen and log-out to be in my LoginScreen again.

(EDIT) My Navigator:

const EintragenStack = createStackNavigator(
  {
    Eintragen: {
      screen: StundenEintragen2,
      navigationOptions: {
        headerTitle: "Stundenverwaltung",
        headerTitleStyle:{
          color: "white",
          alignSelf: "center"
        },
        headerStyle:{
          backgroundColor: "#a51717"
        },  
      }
    }
  }
)

const CheckStack = createStackNavigator(
  {
    Übersicht: StundenChecken,
    Monat: Monatsübersicht2, // Monatsübersicht
    Tag: TagesübersichtDiff, // Tagesübersicht
    Edit: {
      screen: StundenEdit,
      navigationOptions:{
        headerTitle: "Stunden bearbeiten",
        headerTitleStyle: {
          color: "white",
          alignSelf: "center"
        },
        headerStyle: {
          backgroundColor: "#F39237"
        }
      }
    }
  },
  {
    backBehavior: "history"
  }
);
const Tabs = createBottomTabNavigator(
  { 
    Eintragen: EintragenStack,     // StundenEintragen
    Checken: CheckStack,
    Logout: Logout
  },
  {
    backBehavior: "history",
    tabBarOptions: {
      labelStyle: {
        fontSize: 12,
        color: "black"
      },
      activeTintColor: "red",
      activeBackgroundColor: "#ccc"
    }
  }
);
const AppNavigator = createSwitchNavigator({
  Login: Auth, //SecondAuth,
  Tabs: Tabs,
});

EintragenStack.navigationOptions = {   
  tabBarIcon: () => {
    return <Icon style={{marginTop: 5}} size={34} name="ios-add-circle-outline" color="green" />;
  }
  
};
CheckStack.navigationOptions = {
  tabBarIcon: () => {
    return <Icon style={{marginTop: 5}} size={34} name="ios-calendar" color="black" />;
  }
};
Logout.navigationOptions = {
  tabBarIcon: () => {
    return <Icon style={{marginTop: 5}} size={34} name="ios-power" color="red" />;
  }
};

const AppContainer = createAppContainer(AppNavigator);

export default AppContainer;

I actually kind of fixed it for my needs but the problem still exists overall. I don't know if this is a good approach but for me I did it like this:

  1. I am calling checkUnlockHandler in componentWillMount every 30sec.
  2. When checkUnlockHandler gets to an if that tells it that it doesn't need running anymore I call clearInterval(this.interval("here is my checkUnlockHandler"))
  3. After that my interval in componentDidMount stops running which is good.
  4. Problems: Interval still runs in other screens, It feels weird to call a function inside componentDidMount wrapped in a interval and inside this function to tell when the interval should stop.

Upvotes: 5

Views: 3647

Answers (1)

Lahiru Pathum
Lahiru Pathum

Reputation: 56

I faced the same problem in using bottom tab navigator and I found simple solution, which works for me.

    componentDidMount()
    {
        this.props.navigation.addListener('focus', async () =>{
             this.interval= setInterval(() => { 
                 //---------
             }, 5000);
         });
        this.props.navigation.addListener('blur', () => {
            clearInterval(this.interval);
        });
    }

also in functional component we can use useEffect with cleanup.

React.useEffect(() => {
    navigation.addListener('focus', () => {
        this.interval= setInterval(() => { 
                 //---------
        }, 5000);
    });

    return () =>{
        clearInterval(this.interval);
    };
 }, [navigation]);
    

Upvotes: 4

Related Questions