6 votes

Comment puis-je savoir si l'écran est navigué avec ReactNavigation ?

J'aimerais rafraîchir les données à l'écran dans une application react native à chaque fois que l'écran apparaît - comme dans une application de type ViewWillAppear méthode. J'ai essayé d'utiliser la méthode componentWillMount mais il semble qu'elle se déclenche une fois avant d'apparaître, et qu'elle ne se déclenche pas à nouveau lorsque l'on navigue à nouveau vers la vue.

Voici un exemple https://reactnavigation.org/docs/guides/screen-tracking il semble que je puisse ajouter un écouteur sur la page onNavigationStateChange dans le navigateur racine, mais j'aimerais conserver la logique dans l'écran, car il est difficile de s'y retrouver si je déplace la logique de récupération des données pour cet écran à l'extérieur du navigateur racine.

J'ai essayé de suivre l'exemple et de définir cette méthode dans ma stacknavigation, mais elle 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);
      }
    }}
  />

4voto

MonkeyBonkey Points 4169

Voici donc comment j'ai procédé en utilisant la fonction 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);*/}
          }
        }}
      />

Dans votre écran, vous pouvez vérifier si votre vue apparaîtra. 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
    }
  }

1voto

Travis White Points 1408

Voici mon réducteur de navigateurs.

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;
}

Ensuite, nous devons connecter le module/route au magasin redux (sceneIsActive est l'élément 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, à l'intérieur de votre composant, vous pouvez surveiller/déclencher du code 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. N'oubliez donc pas d'appeler votre doSomethingWhenScreenBecomesActive là aussi.

1voto

Kinko Points 219

Vous pouvez utiliser des récepteurs d'événements focus/blur (démontrés aquí et a discuté aquí ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X