`componentDidMount()` function is not called after navigation

后端 未结 9 1788
旧巷少年郎
旧巷少年郎 2020-12-09 03:38

I am using stackNavigator for navigating between screens. I am calling two API\'s in componentDidMount() function in my second activity. When i loa

相关标签:
9条回答
  • 2020-12-09 03:51

    You want to perform something after every time navigating to a component using drawernavigator or stacknavigator ; for this purpose NavigationEvents fits better than componentDidMount .

    import {NavigationEvents} from "react-navigation";
    <NavigationEvents onDidFocus={()=>alert("Hello, I'm focused!")} />
    

    Note : If you want to do the task every time after focusing on a component using drawer navigation or stack navigation then using NavigationEvents is better idea. But if you want to do the task once then you need to use componenetDidMount .

    0 讨论(0)
  • 2020-12-09 03:58

    Solution for 2020 / React Navigation v5

    Inside your screen's ComponentDidMount

    componentDidMount() {
        this.props.navigation.addListener('focus', () => {
          console.log('Screen.js focused')
        });
    }
    

    https://reactnavigation.org/docs/navigation-events/

    Alternatively: Put the addListener method in constructor instead to prevent duplicated calls

    0 讨论(0)
  • 2020-12-09 04:02

    If the upvoted syntax that uses NavigationEvents component is not working, you can try with this:

    // no need to import anything more
    
    // define a separate function to get triggered on focus
    onFocusFunction = () => {
      // do some stuff on every screen focus
    }
    
    // add a focus listener onDidMount
    async componentDidMount () {
      this.focusListener = this.props.navigation.addListener('didFocus', () => {
        this.onFocusFunction()
      })
    }
    
    // and don't forget to remove the listener
    componentWillUnmount () {
      this.focusListener.remove()
    }
    
    0 讨论(0)
  • 2020-12-09 04:04

    If anyone coming here in 2019, try this:

    import {NavigationEvents} from 'react-navigation';
    

    Add the component to your render:

    <NavigationEvents onDidFocus={() => console.log('I am triggered')} />
    

    Now, this onDidFocus event will be triggered every time when the page comes to focus despite coming from goBack() or navigate.

    0 讨论(0)
  • 2020-12-09 04:04

    In React, componentDidMount is called only when component is mounted.I think what you are trying to do is call your API on going back in StackNavigator. You can pass a callback function as parameter when you call navigate like this on Parent Screen:

      navigate("Screen", {
         onNavigateBack: this.handleOnNavigateBack
      }); 
      handleOnNavigateBack = () => {//do something};
    

    And on Child Screen

    this.props.navigation.state.params.onNavigateBack();
    this.props.navigation.goBack();
    
    0 讨论(0)
  • 2020-12-09 04:06

    The React-navigation documentation explicitly described this case:

    Consider a stack navigator with screens A and B. After navigating to A, its componentDidMount is called. When pushing B, its componentDidMount is also called, but A remains mounted on the stack and its componentWillUnmount is therefore not called.

    When going back from B to A, componentWillUnmount of B is called, but componentDidMount of A is not because A remained mounted the whole time.

    Now there is 3 solutions for that:

    Subscribing to lifecycle events

    ...

    React Navigation emits events to screen components that subscribe to them. There are four different events that you can subscribe to: willFocus, willBlur, didFocus and didBlur. Read more about them in the API reference.

    Many of your use cases may be covered with the withNavigationFocus higher-order-component, the <NavigationEvents /> component, or the useFocusState hook.

    1. the withNavigationFocus higher-order-component
    2. the <NavigationEvents /> component
    3. the useFocusState hook (deprecated)

    withNavigationFocus higher-order-component

    import React from 'react';
    import { Text } from 'react-native';
    import { withNavigationFocus } from 'react-navigation';
    
    class FocusStateLabel extends React.Component {
      render() {
        return <Text>{this.props.isFocused ? 'Focused' : 'Not focused'}</Text>;
      }
    }
    
    // withNavigationFocus returns a component that wraps FocusStateLabel and passes
    // in the navigation prop
    export default withNavigationFocus(FocusStateLabel);
    

    <NavigationEvents /> component

    import React from 'react';
    import { View } from 'react-native';
    import { NavigationEvents } from 'react-navigation';
    
    const MyScreen = () => (
      <View>
        <NavigationEvents
          onWillFocus={payload => console.log('will focus', payload)}
          onDidFocus={payload => console.log('did focus', payload)}
          onWillBlur={payload => console.log('will blur', payload)}
          onDidBlur={payload => console.log('did blur', payload)}
        />
        {/*
          Your view code
        */}
      </View>
    );
    
    export default MyScreen;
    

    useFocusState hook

    First install library yarn add react-navigation-hooks

    import { useNavigation, useNavigationParam, ... } from 'react-navigation-hooks'
    
    function MyScreen() {   const focusState = useFocusState();   return <Text>{focusState.isFocused ? 'Focused' : 'Not Focused'}</Text>; }
    

    Here is my personal solution, using onDidFocus() and onWillFocus() to render only when data has been fetched from your API:

    import React, { PureComponent } from "react";
    import { View } from "react-native";
    import { NavigationEvents } from "react-navigation";
    
    class MyScreen extends PureComponent {
      state = {
        loading: true
      };
    
      componentDidMount() {
        this._doApiCall();
      }
    
      _doApiCall = () => {
        myApiCall().then(() => {
          /* Do whatever you need */
        }).finally(() => this.setState({loading: false}));
      };
    
      render() {
        return (
          <View>
            <NavigationEvents 
                  onDidFocus={this._doApiCall} 
                  onWillFocus={() => this.setState({loading: true})}
            />
            {!this.state.loading && /*
            Your view code
            */}
          </View>
        );
      }
    }
    
    export default MyScreen;
    
    0 讨论(0)
提交回复
热议问题