Как получить текущее название маршрута в React-Navigation?

Мне нужно имя текущего маршрута или экрана в реакции-навигации, которое я хочу использовать внутри условия if, чтобы внести некоторые изменения.

Как это возможно теперь в React-Navigation v5?

Dimitri Kopriwa 06.02.2020 13:19

React - это такая неразбериха со всеми изменениями между версиями. В документации ничего из этого не упоминается, и код кажется трудным для понимания, мне интересно, как люди вообще придумали эти (старые) решения.

Kevin 20.04.2020 05:56

каким-либо способом для 'wix / react-native-navigation', чтобы получить текущий экран?

Vandit Mehta 18.12.2020 11:48
63
3
110 157
23
Перейти к ответу Данный вопрос помечен как решенный

Ответы 23

При использовании "react-navigation": "^3.0.8" и DrawerNavigator к нему можно получить доступ из объекта this.props, используя this.props.activeItemKey

с DrawerNavigator он работает, вы используете то же самое?

Rishabh 25.03.2019 12:29

Если вы используете вложенные навигаторы, например StackNavigator внутри DrawerNavigator, и вам нужен activeItemKey внутри ящиков contentComponent, как бы вы его получили?

cseelus 20.04.2019 19:44

для одного маршрута это работает для меня this.props.navigation.state.routeName

JHOAN B. HENRICHE 26.11.2019 22:06
Ответ принят как подходящий

Вы можете поймать это как следующий код:

this.props.navigation.state.routeName

Этот ответ работает с StackNavigator. Предыдущий ответ this.props.activeItemKey не работает.

lucius degeer 25.03.2019 18:31

Идеально работает с навигатором верхней вкладки материала в defaultNavigationOptions.

CyberMew 23.08.2020 00:42

Привет, надеюсь, у тебя все хорошо. Не могли бы вы взглянуть на мой вопрос? stackoverflow.com/questions/66548327/…, спасибо

kd12345 17.03.2021 13:44

как мне проверить текущее имя маршрута ящика в дочернем стеке

Areeb Vohra 22.05.2021 13:32

Если вы используете вложенные навигаторы, вы можете использовать этот код для получения текущего состояния активного экрана.

import { NavigationState } from 'react-navigation';

const getActiveRouteState = function (route: NavigationState): NavigationState {
    if (!route.routes || route.routes.length === 0 || route.index >= route.routes.length) {
        return route;
    }

    const childActiveRoute = route.routes[route.index] as NavigationState;
    return getActiveRouteState(childActiveRoute);
}

Использование:

const activeRoute = getActiveRouteState(this.props.navigation.state);

Я использую это, когда мне нужно получить текущее состояние активного экрана из NavigationDrawer.

Я думаю, этот ответ более общий

chenop 18.11.2019 15:28

Как вы вводите маршрут в специальный ящик?

Sanchitos 20.04.2020 19:47

Откуда приходит NavigationState?

Hugo 30.07.2020 11:12

@Hugo NavigationState - это импорт из react-navigation

gianlucaparadise 05.08.2020 11:22

У меня есть несколько TabNavigator, вложенных в BottomTabNavigator. Я получаю текущий маршрут TabNavigator с:

    const pathAndParams = props.navigation.router.getPathAndParamsForState(props.navigation.state) || {}
    const activePath = pathAndParams.path

Подготовка

Зарегистрируйте ?NavigationService.js, см. детали документа в Навигация без навигационной опоры

<App
  ref = {navigatorRef => {
        NavigationService.setTopLevelNavigator(navigatorRef);
  }}
/>

функция рекурсии

function getCurrentRoute(nav){
    if (Array.isArray(nav.routes)&&nav.routes.length>0){
        return getCurrentRoute(nav.routes[nav.index])
    }else {
        return nav.routeName
    }
}

получить текущее имя маршрута

getCurrentRoute(NavigationService.getNavigator().state.nav)

Для реакции-навигации v5 вы можете использовать хук useNavigationState -

import {useNavigationState} from '@react-navigation/native';

const state = useNavigationState(state => state);
const routeName = (state.routeNames[state.index]);
console.info(routeName);

Для реакции-навигации v5:

import {useRoute} from '@react-navigation/native';

const route = useRoute();
console.info(route.name);

Вы не указали, в каком месте мне следует использовать этот метод useRoute (). Я получаю, что хуки можно вызывать только внутри тела функционального компонента.

Aleksandrs 03.01.2021 13:02

Как идентифицировать этот сценарий? Переход прямо к экрану контактов. И переход к экрану контактов через главный экран.

M.Kalidass 13.04.2021 12:33

как мне проверить текущий маршрут ящика?

Areeb Vohra 22.05.2021 13:30

Это отлично работает в react-navigation v5.x

this.props.route.name

В React Navigation v5 я смог извлечь текущее имя маршрута с помощью следующего подхода:

import { useNavigationState } from '@react-navigation/native'    

const routes = useNavigationState(state => state.routes)
const currentRoute = routes[routes.length -1].name
console.info('currentRoute: ',currentRoute)
const routeNameRef = React.createRef();

<NavigationContainer
  ref = {navigationRef}
  onReady = {() => routeNameRef.current = navigationRef.current.getCurrentRoute().name}
  onStateChange = {() => {
    const previousRouteName = routeNameRef.current
    const currentRouteName = navigationRef.current.getCurrentRoute().name

    if (previousRouteName !== currentRouteName) {
      // Do something here with it
    }

    // Save the current route name for later comparision
    routeNameRef.current = currentRouteName
  }}
  >
  {/* ... */}
</NavigationContainer>
  );

export function getCurrentRouteName(action) {
  return routeNameRef;
}

Вы можете импортировать функцию getCurrentRouteName и использовать ее, чтобы получить имя текущего маршрута и его работу во всех вложенных навигаторах в React Navigation 5.

Остерегайтесь этого Попался

Anand Rockzz 03.03.2021 20:37

this.props.navigation.state.routeName работает только в react-navigation 4, но react-navigation 5 его не поддерживает.

Текущее имя маршрута может быть получено с помощью redux:

-Компонент навигатора передает объект маршрута как опору дочернему компоненту

-Дочерний компонент получает реквизиты и может найти имя маршрута в route.name

-Чтобы получить обновленное имя маршрута при изменении экрана, вы можете использовать прослушиватель событий фокус при навигации

<====== Родительский компонент, в котором реализована навигация ======>

import React from "react";
import { createMaterialTopTabNavigator } from "@react-navigation/material-top- 
tabs";

import ChildScreen from "../screens/Home/childScreen";

const Tab = createMaterialTopTabNavigator();

const ParentNavigations = () => {

return (

<Tab.Navigator
>
  <Tab.Screen name = "ChildScreen" component = {ChildScreen} />
</Tab.Navigator>
);
};

export default ParentNavigations;

<===== Дочерний компонент =====>

import React, { useEffect } from "react";
import { View, StyleSheet } from "react-native";
import { useDispatch } from "react-redux";
import ActionTypes from "../../store/actions/ActionsTypes";

const ChildScreen = ({ navigation, route }) => {
  const dispatch = useDispatch();
  useEffect(() => {
    const unsubscribe = navigation.addListener("focus", () => {
      dispatch({ type: ActionTypes.SETROUTE, payload: route.name }); // every time when screen gets focued it will update the route through redux
    });
    return unsubscribe;
  }, [navigation, route]);
  return (
    <View style = {styles.container}>
      <Text>Hello</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#0C0B0B",
  },
});

export default ChildScreen;

Если вы просто хотите увидеть, сфокусирован ли текущий экран, вы можете использовать navigation.isFocused (). https://reactnavigation.org/docs/navigation-prop/#isfocused

Пример:

_backAction() {
    const { navigation } = this.props;
    if (navigation.isFocused()) {
        this.setState({
            isLeavingApp: true,
        });
    }
}

Это сработало для меня (я сделал это в моем навигационном ящике)!

const getCurrentRoute = nav => {
  if (Array.isArray(nav.routes) && nav.routes.length > 0) {
    return getCurrentRoute(nav.routes[nav.index]);
  } else {
    return nav.routeName;
  }
};

const currentNavigation = getCurrentRoute(this.props.navigation.state);

С версией 5.x лучший способ на данный момент - getFocusedRouteNameFromRoute

import { getFocusedRouteNameFromRoute } from '@react-navigation/native';

export default function Stack(route) {
  // If the focused route is not found, we need to assume it's the initial screen
  // This can happen during if there hasn't been any navigation inside the screen
  // In our case, it's "Feed" as that's the first screen inside the navigator
  const routeName = getFocusedRouteNameFromRoute(route) ?? 'Feed';
  return <> ..... </>
}
import { useNavigation } from '@react-navigation/native';

const App = () => {
  const navigation = useNavigation();
  const { dangerouslyGetState } = useNavigation();
  const { index, routes } = dangerouslyGetState()
  console.info(routes[index].name);

  return(
    <>
    </>
  )
};

это сработало для меня, попробуйте это ..

const getCurrentRouteName = () => {
    let _index = props.state.index;
    let _routeName = props.state.routeNames;
    return  _routeName[_index]
}

Для wix / response-native-navigation ниже мое рабочее решение,

import { Navigation } from 'react-native-navigation';

// Create a variable and set the value from navigation events
let navComponent = null
Navigation.events().registerComponentDidAppearListener(event => navComponent = event)

// navComponent will have the following structure
{"componentId": "Component9", "componentName": "HomeScreen", "componentType": "Component", "passProps": {}}

Это можно получить из navigationRef, прикрепленного к контейнеру навигации. Где navigationRef - исх.

export const navigationRef = React.createRef()

<NavigationContainer
   ref = {navigationRef} 
   >
  <Navigator />
</NavigationContainer>

Затем используйте: const currentRouteName = navigationRef.current.getCurrentRoute().name

В качестве альтернативы в функциональном компоненте можно использовать Ref const navigationRef = React.useRef()

const Home = ({ navigation, route }) => {
  // you will see screen key, name and params
  console.info("ROUTE", route); 
  // rest of your code
};

Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.

mufazmi 21.05.2021 20:20

Вы также можете использовать это в крючках.

console.info(navigation.dangerouslyGetState());

Для реагирования на родную навигацию 5.x используйте:

props.state.routeNames[props.state.index]

Это пошаговая процедура того, что Джастин Мэтью описал в своем ответе.

Создайте новый файл с именем RootNavigation.js и поместите в него содержимое ниже.

// RootNavigation.js

import * as React from 'react';

export const navigationRef = React.createRef(); // we will access all navigation props by importing this in any of the component

Теперь импортируйте navigationRef из файла RootNavigation.js и назначьте ему ссылку NavigationContainer. После этого шага navigationRef может глобально функционировать как навигационная опора.

// App.js

import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from './RootNavigation';

export default function App() {
  
  handleNavigationRef = (ref) => {
    // DON'T DO navigationRef = ref, cause this will give you "navigationRef is 
    // read only" error.
    navigationRef.current = ref; 
  }
  return (
     <NavigationContainer ref = {handleNavigationRef}>
        {/* ... */} 
     </NavigationContainer>
  );
}

ИСПОЛЬЗОВАНИЕ

Теперь вы можете импортировать navigationRef в любой файл, даже во вложенный. И можете использовать это, чтобы получить информацию о текущем маршруте и экране.

//SomeNestedComonent.js

import { navigationRef } from "path/to/RootNavigation.js/file";

const route = navigationRef.current?.getCurrentRoute(); //current route object
const currentScreen = route.name; // current screen name

В моем случае мне также нужно было получить индекс нижняя навигация, это был мой метод

import {useNavigationState} from '@react-navigation/native';

тогда

const routes = useNavigationState(state => state.routes);

let place = routes[routes.length - 1];

if (place.name === 'YOUR_BOTTOM_NAV_NAME') {
   if (place.state.index === 0) {
      //you are in the main screen(BOTTOM_NAV : index 0)
   } else {
      //else navigate to index 0 screen
      navigation.navigate('FirstScreen');
   }
} else if (place.name === 'Another_Screen') {
   navigation.navigate('navigate_to_the_place_you_want');
} else {
   //otherwise come to the first screen
   navigation.navigate('FirstScreen');
}

Другие вопросы по теме