How to trigger an event when a component is shown when using react-native-navigation?

前端 未结 6 1545
野趣味
野趣味 2021-02-02 09:35

I am using react-native with react-native-navigation. I would like to reload data when a component is shown. The component is shown when a user clicks on a tab navigation button

相关标签:
6条回答
  • 2021-02-02 09:37

    include this as 'callIfBackToThisRoute'...

    export default ( props, call ) => {
        if( !props.navigation ) throw 'I need props.navigation'
        const thisRoute = props.navigation.state.routeName;
        props.navigation.addListener(
            'willFocus',
            payload => {
                if( payload.state.routeName == thisRoute) call(props)
            }
        );
    }
    

    and use it inside your component...

    componentDidMount() {
        const { doIt } = this.props;
        doIt()
        callIfBackToThisRoute(
            this.props,
            (props) => doIt()
        )
    }
    
    0 讨论(0)
  • 2021-02-02 09:44

    This is what I ended up using:

    export default class RootNavigator extends React.Component {
      state = {currentScreen: null}
    
      _onNavigationStateChange(prevState, newState, action) {
        // const currentScreen = getCurrentRouteName(currentState)
        // const prevScreen = getCurrentRouteName(prevState)
        // console.debug('onNavigationStateChange currentScreen=', currentScreen,
        //   'prevScreen=', prevScreen, 'action.routeName=', action.routeName)
        console.debug('onNavigationStateChange action.routeName=', action.routeName)
        this.setState({currentScreen: action.routeName})
      }
    
      render() {
        return <RootStackNavigator onNavigationStateChange={this._onNavigationStateChange.bind(this)}
          screenProps={{currentScreen: this.state.currentScreen}}/>;
      }
    

    coupled with componentDidUpdate() on the screen (which may or may not perform something depending on the screenProps's currentScreen).

    Note: I don't know what/where getCurrentRouteName() is and it gave error for me so I don't use it and use action.routeName directly.

    See https://github.com/react-community/react-navigation/issues/2371 and https://github.com/react-community/react-navigation/issues/51#issuecomment-323536642 for more information and discussion.

    0 讨论(0)
  • 2021-02-02 09:52

    For RNN v3, after trying out for quite a couple times, I finally figured out the correct way:

      componentDidMount() {
        this.navigationEventListener = Navigation.events().bindComponent(this);
      }
    
      componentWillUnmount() {
        if (this.navigationEventListener) {
          this.navigationEventListener.remove();
        }
      }
    
      componentDidAppear() {   // Lazy loading data for RNN
        if (this.state.routes.length === 0) {
          this.getData();
        }
      }
    

    The key is that, the binding of event listener is mandatory, otherwise the componentDidAppear() and componentDidDisappear() won't be triggered.

    0 讨论(0)
  • 2021-02-02 09:58

    The currently accepted answer suggests a react-navigation solution, not react-native-navigation (RNN), so I'll go ahead and give my two cents.

    As Stephen Liu points out in his answer, RNN provides screen lifecycle methods that fire when a component appears (componentDidAppear) and disappears (componentDidDisappear).

    Stephen's answer works for a class component, however in the age of hooks I prefer function components. So this is how to use RNN's screen lifecycle methods in a function component:

    import React, { useEffect } from 'react'
    import { Navigation } from 'react-native-navigation'
    
    const MyComponent = ({ componentId }) => {
    
      useEffect(() => {
        const navListener = Navigation.events().bindComponent(this, componentId)
    
        // remove the listener during cleanup
        return () => {
          navListener.remove()
        }
      }, [componentId])
    
      this.componentDidAppear = () => {
        // do stuff when component appears
      }
    
      this. componentDidDisappear = () => {
        // do stuff when component disappears
      }
    
    }
    
    

    Important: MyComponent needs a componentId prop, which is injected automatically if it's a registered RNN screen or modal (Navigation.registerComponent). You can also manually pass it down from a screen component to the child where you need it.

    0 讨论(0)
  • 2021-02-02 09:59

    I like the solution proposed by Bruno Reis. I tweaked mine to make it a bit simpler.

    class Whatever extends Component {
        componentDidMount(){
            this.load()
            this.props.navigation.addListener('willFocus', this.load)
        }
        load = () => {
            ...
        }
    
    }
    
    0 讨论(0)
  • 2021-02-02 10:02

    Override componentWillMount lifecycle method: https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount Or just put the functionality inside render method

    0 讨论(0)
提交回复
热议问题