web-dev-qa-db-fra.com

Réagir Navigation: Revenir à la racine à l'aide de NavigationActions.reset, goBack et getStateForAction

Supposons que j'ai navigué sur 4 écrans dans mon application StackNavigator et que je souhaite maintenant revenir au premier écran. Il semble y avoir trois façons différentes de le faire et ils naviguent où je veux, cependant chaque animation a une animation qui parcourt chaque écran précédent. 

Existe-t-il un moyen simple de naviguer de SCREEN_D à SCREEN_A

En d'autres termes, je ne veux pas voir SCREEN_C et SCREEN_B une fraction de seconde avant de voir SCREEN_A lors de la navigation à partir de SCREEN_D

navigation.navigate(SCREEN_A);
...
navigation.navigate(SCREEN_B);
...
navigation.navigate(SCREEN_C);
...
navigation.navigate(SCREEN_D);

Trois façons de faire ceci:

1.

return this.props.navigation
               .dispatch(NavigationActions.reset(
                 {
                    index: 0,
                    actions: [NavigationActions.navigate({ routeName: 'SCREEN_A'})]
                  }));

2.

 const {SCREEN_B_KEY} = this.props.navigation.state.params
 this.props.navigation.goBack(SCREEN_B_KEY)

3.

const defaultGetStateForAction = Navigation.router.getStateForAction;

Navigation.router.getStateForAction = (action, state) =>{
  if(action.type === "Navigation/BACK"){
    const routes = [
      {routeName: 'First'},
    ];
    return {
      ...state,
      routes,
      index: 0,
    };
  }
  return defaultGetStateForAction (action,state);
}
23
Turnipdabeets

Voici une solution rapide ... Ceci supprimera TOUTES les transitions lors de la navigation (avant ou arrière). 

const Nav = StackNavigator({
  Screens
},{
  transitionConfig,
  navigationOptions
});

dans transitionConfig, ajoutez ceci:

const transitionConfig = () => ({
    transitionSpec: {
      duration: 0,
      timing: Animated.timing,
      easing: Easing.step0,
    },
  })

TransitionConfig est une fonction qui renvoie un objet qui remplace les transitions d'écran par défaut. https://reactnavigation.org/docs/navigators/stack

  • si quelqu'un connaît un moyen de changer les animations en navigation simple, j'aimerais savoir comment!
7
Turnipdabeets

Vous pouvez le faire en utilisant la méthode popToTop à partir de Navigation prop . De plus, si vous utilisez redux, vous devez mettre à jour votre intégration Redux .

J'espère que cela t'aides! 

4
Denny Schuldt

Également passé du temps là-dessus, laissez-moi résumer ce que j'ai découvert, il existe plusieurs solutions/solutions de contournement pour cela:

1) Utilisez CardStackStyleInterpolator

La demande pull mentionnée par Cristiano Santos semble être fusionnée. Vous pouvez donc charger la CardStackStyleInterpolator avec cette importation:

import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator'

Pour l'appliquer comme ceci:

const YourStackNavigator = StackNavigator({
    Screen1: { screen: Screen1 },
    Screen2: { screen: Screen2 },
}, {
    transitionConfig: () => ({
        screenInterpolator: (props) => CardStackStyleInterpolator.forHorizontal(props)
    })
});

Dans mon cas, je passe simplement à l'écran suivant, comme suit:

this.props.navigation.navigate('Modal_AddGoodClass');

Mais dans mon réducteur, je réinitialise le navigateur lorsque l'écran Modal_AddGoodClass est déclenché:

const NewExportReceiptNavigationReducer = (state, action) => {
    // Default stuff

    let newStateBuffer = newState || state;

    if (action) {
        if (action.type === 'Navigation/NAVIGATE') {
            if (action.routeName === 'Modal_AddGoodClass') {
                newStateBuffer = {
                    index:  0,
                    routes: [
                        newStateBuffer.routes[newStateBuffer.routes.length - 1]
                    ]
                };
            }
        }
    }

    return newStateBuffer;
};

module.exports = NewExportReceiptNavigationReducer;

Cela fonctionne plutôt bien, sauf le fait qu'une animation "en arrière" est toujours utilisée au lieu d'une animation "en avant".

Vous pouvez également trouver ici des exemples de code utilisant CardStackStyleInterpolator.

2) Écraser getStateForAction:

Comme Fendrian a mentionné ici , vous pouvez écraser getStateForAction de votre routeur pour éviter que le navigateur ne retourne. Cela semble fonctionner sauf pour le geste "glisser en arrière" sur iOS:

Nav = StackNavigator(navScreens, navOptions);
const defaultGetStateForAction = Nav.router.getStateForAction;
Nav.router.getStateForAction = (action, state) => {
  if (
    state &&
    action.type === NavigationActions.BACK &&
    (
      state.routes[state.index].routeName === 'Login' ||
      state.routes[state.index].routeName === 'Main'
    )
  ) {
    // Returning null indicates stack end, and triggers exit
    return null;
  }
  return defaultGetStateForAction(action, state);
};

nov-05-2017 11-34-07

0
Thomas Kekeisen

Ceci est ma solution de travail pour réinitialiser à la maison (racine) sans créer de nouvelle route

if(this.categoriesNav.state.nav.index >0){
    let k = this.categoriesNav.state.nav.routes[1].key;
    this.categoriesNav.dispatch(NavigationActions.back({key: k})); }

categoriesNav est référencé à mon navigateur de pile

0
Masoud Teymouri