web-dev-qa-db-fra.com

Réagir Navigation 2: Comment vérifier la scène précédente et désactiver le changement d'onglet

J'ai un onglet de navigation. Un de mes onglets a un formulaire et je voudrais désactiver l’événement de navigation si mes données de formulaire ne sont pas enregistrées.

Dans la version 1, la méthode tabBarOnPress fournit previousScene, scene et jumpToIndex, ce qui m'a permis de vérifier la scène que je quittais et d'accéder à ses accessoires. 

Maintenant dans la version 2, la méthode tabBarOnPress fournit les accessoires navigation pour la scène, mais l’accessoire de la scène précédente est manquant: /

navigationOptions: {
    tabBarOnPress: ({ navigation, defaultHandler }) => {
        // Check the previous screen
        // If I am leaving the home screen and the user has unsaved data
        // disable tab navigation
        // else change to the pressed tab
    },
},

De plus, j'ai essayé avec les écouteurs d'événement de navigation mais l'action NAVIGATE est déjà distribuée:

props.navigation.addListener('willBlur', () => {
    // Disable tab switching;
}),

Collation simple: https://snack.expo.io/@hristoeftimov/handle-tab-changes-in-react-navigation-v2

Des solutions comment désactiver le changement de tabulation avant de laisser un onglet?

9
Hristo Eftimov

J'ai trouvé un moyen beaucoup plus simple, en utilisant le getStateForAction.

const defaultGetStateForAction = MainStack.router.getStateForAction;
MainStack.router.getStateForAction = (action, state) => {
    if (!state) {
        return defaultGetStateForAction(action, state);
    }

    if (
        action.type === NavigationActions.NAVIGATE
        && state.routes[state.index].key === 'HomeTab'
    ) {
        const tab = state.routes[state.index];
        const currentRoute = tab.routes[tab.index];
        const currentRouteParams = currentRoute.params;

        if (currentRouteParams && currentRouteParams.isNavigationDisabled) {
            return currentRouteParams.showConfirmationDialog(action);
        }
    }

    return defaultGetStateForAction(action, state);
}

Chaque fois que je bascule entre les onglets, je saute dans getStateForAction où je peux accéder à l'onglet qui part (de state) et à l'écran suivant (à partir de action).

Ainsi, lorsque mon action est NAVIGATE et que l'écran/la route de sortie est HoneTab, je peux modifier/désactiver l'état par défaut de l'action et déclencher showConfirmationDialog() - Il s'agit d'une fonction que je peux définir comme paramètre de route pour mon écran HomeTab.

0
Hristo Eftimov

L'objet navigation contient les données dont vous avez besoin, car il conserve l'état de navigation avant la navigation vers le nouvel onglet. Cet état de navigation a à la fois l'écran à partir duquel vous naviguez et ses paramètres.

Pour obtenir l'état, vous pouvez utiliser la fonction suivante:

function getCurrentRoute(navState) {
  if (!navState) {
    return null;
  }
  const route = navState.routes[navState.index];

  if (route.routes) {
    return getCurrentRoute(route); // nested routes
  } else {
    return {
      name: route.routeName,
      params: { ...route.params }
    };
  }
}

Alors maintenant, vous pouvez utiliser cette fonction dans le gestionnaire onPress. Quelque chose comme ça:

navigationOptions: {
    tabBarOnPress: ({ navigation, defaultHandler }) => {
        const currentRoute = getCurrentRoute(navigation.state);
        if (currentRoute.name !== 'Home' || !currentRoute.params.isNavigationDisabled) {
            defaultHandler();
        }
    }
}

Bien entendu, cela signifie que vous devrez gérer un paramètre de navigation appelé isNavigationDisabled dans votre écran d’accueil à l’aide de la méthode this.props.navigation.setParams.

De plus, j'espère avoir correctement corrigé le nom d'écran, si ce n'est simplement le déboguer.

0
Asaf David