web-dev-qa-db-fra.com

Comment savoir si l'écran avec ReactNavigation est navigué

J'aimerais actualiser les données à l'écran dans une application native native à chaque fois que l'écran apparaît - comme dans une méthode ViewWillAppear. J'ai essayé d'utiliser la méthode componentWillMount, mais il semble qu'elle se déclenche une fois avant son affichage et ne se déclenche pas à nouveau lorsque vous revenez à la vue.

En regardant cet exemple https://reactnavigation.org/docs/guides/screen-tracking , il semble que je puisse ajouter un écouteur à la méthode onNavigationStateChange dans la navigation racine, mais j'aimerais conserver la logique. à l'écran car cela devient confus si je déplace la logique d'extraction de données pour cet ébauche vers le navigateur racine.

J'ai essayé de suivre l'exemple et de définir cette méthode sur stacknavigation mais cela ne semble pas se déclencher.

  <RootNavigation ref={nav => { this.navigator = nav; }}
    onNavigationStateChange={(prevState, currentState, action) => {

      // maybe here I can fire redux event or something to let screens
      // know that they are getting focus - however it doesn't fire so
      // I might be implementing this incorrectly

      const currentScreen = getCurrentRouteName(currentState);
      const prevScreen = getCurrentRouteName(prevState);

      if (prevScreen !== currentScreen) {
        console.log('navigating to this screen', currentScreen);
      }
    }}
  />
6
MonkeyBonkey

Alors voici comment je l’ai fait avec la variable onNavigateStateChange.

      <RootNavigation
        ref={nav => { this.navigator = nav; }}
        uriPrefix={prefix}
        onNavigationStateChange={(prevState, currentState) => {
          const currentScreen = this.getCurrentRouteName(currentState);
          const prevScreen = this.getCurrentRouteName(prevState);
          if (prevScreen !== currentScreen) {
            this.props.emitActiveScreen(currentScreen);
            {/*console.log('onNavigationStateChange', currentScreen);*/}
          }
        }}
      />

Et sur votre écran, vous pouvez vérifier si votre vue apparaîtra, notez que MyPage est le nom de l'itinéraire de votre objet de navigation.

  componentWillReceiveProps(nextProps) {
    if ((nextProps.activeScreen === 'MyPage' && nextProps.activeScreen !== this.props.activeScreen)) {
      // do your on view will appear logic here
    }
  }
4
MonkeyBonkey

Voici mon réducteur de navigateur.

function getCurrentRouteName(navState) {
  if (!navState) {
    return null;
  }

  const navigationState = (navState && navState.toJS && navState.toJS()) || navState;

  const route = navigationState.routes[navigationState.index];
  // dive into nested navigators
  if (route.routes) {
    return getCurrentRouteName(route);
  }

  return route.routeName;
}


export default function NavigatorReducer(state, action) {
  // Initial state
  if (!state) {
    return fromJS(AppNavigator.router.getStateForAction(action, state));
  }

  // Is this a navigation action that we should act upon?
  if (includes(NavigationActions, action.type)) {
    // lets find currentScreen before this action based on state
    const currentScreen = getCurrentRouteName(state);
    const nextState = AppNavigator.router.getStateForAction(action, state.toJS());
    // determine what the new screen will be after this action was performed
    const nextScreen = getCurrentRouteName(nextState);

    if (nextScreen !== currentScreen) {
      nextState.currentRoute = nextScreen;
      console.log(`screen changed, punk: ${currentScreen} -> ${nextScreen}`);
    }

    return fromJS(nextState);
  }

  return state;
}

Et ensuite, nous devons connecter le module/la route au magasin Redux (sceneIsActive est le bit important):

export default connect(
  state => ({
    counter: state.getIn(['counter', 'value']),
    loading: state.getIn(['counter', 'loading']),
    sceneIsActive: state.getIn(['navigatorState', 'currentRoute']) === 'Counter',
  }),
  dispatch => {
    return {
      navigate: bindActionCreators(NavigationActions.navigate, dispatch),
      counterStateActions: bindActionCreators(CounterStateActions, dispatch),
    };
  },
)(CounterView);

Ensuite, dans votre composant, vous pouvez surveiller le code/trigger lorsque la scène devient active:

  componentWillReceiveProps(nextProps) {
    if (nextProps.sceneIsActive && (this.props.sceneIsActive !== nextProps.sceneIsActive)) {
      console.log('counter view is now active, do something about it', this.props.sceneIsActive, nextProps.sceneIsActive);
      doSomethingWhenScreenBecomesActive();
    }
  }

Sachez que componentWillReceiveProps ne s'exécute pas lors du montage initial. Alors, n'oubliez pas d'appeler votre doSomethingWhenScreenBecomesActive également.

1
Travis White

Vous pouvez utiliser les écouteurs d’événement focus/flou (démonstration ici et discussion ici ).

1
Kinko