如何从React Navigation获取上一个路由名称

27
我试图获取当前屏幕的上一个路由名称。因为根据上一个屏幕的名称,我必须在当前屏幕中显示/隐藏一些对象。
为了获取上一个屏幕的名称,我尝试了以下方法:
componentDidMount() {
    const { navigation } = this.props;
    if (navigation.state.params && navigation.state.params.previous_screen) {
       console.log('navigation.state.params.previous_screen', navigation.state.params.previous_screen);
    }
}

但是,在控制台日志中出现 undefined

有任何建议吗?


1
为什么您不接受对您问题的答案?如果提供的答案不起作用,至少请评论并说明它没有起作用。 - Junius L
@TenTenPeter,我已经说过我检查过了,但是还是不行,而且显示未定义。请检查我的上面的评论。它没有起作用。即使那些答案没有起作用,我也不想给他们投反对票。 - Anilkumar iOS - ReactNative
你能分享一下代码吗?因为这段代码在我的环境中是可以正常工作的。我还添加了一个演示。 - Junius L
@AnilkumariOSReactNative 请查看 https://stackoverflow.com/help/someone-answers 并查看下面的代码,Junius L 的回答应该能解决你的问题。 - Junius L
答案来自Junius,已经起作用。 - Anilkumar iOS - ReactNative
显示剩余4条评论
10个回答

23

对于堆栈导航器(Stack Navigators),我使用以下代码在 react-navigation v6 中动态获取上一个路由名称:

// `navigation` const is passed to the screen component or from useNavigation()
const routes = navigation.getState()?.routes;
const prevRoute = routes[routes.length - 2]; // -2 because -1 is the current route

注意:这对于动态地将参数传递回到先前的屏幕非常有用。但请注意嵌套路由,语法略有不同。

if (prevRoute.name === "<Some Routing Key>") {
      navigation.navigate("<Some Routing Key>", params);
}

为什么我会收到“name未定义”的警告消息,针对prevCode? - On the way to success
3
更好的方法是使用 useNavigationState 钩子,因为他们建议不要以那种方式使用 navigation.getState()?.routes;文档 - Bartłomiej Tuchowski
@BartłomiejTuchowski 文档中指出:“useNavigationState是一个钩子函数,用于访问包含屏幕的导航器的导航状态”。这意味着它在嵌套导航器中无法用于父导航器。 - undefined

9
你需要使用 NavigationActions
goToScreen = () => {

  const navigateAction = NavigationActions.navigate({
    routeName: 'Profile',

    params: { previous_screen: 'Home' }, // current screen

    action: NavigationActions.navigate({ routeName: 'Profile' }), // screen you want to navigate to
  });

  this.props.navigation.dispatch(navigateAction);
  
};

在你的onPress中调用上述函数。

<Text onPress={this.goToScreen}>Go to screen</Text>

在你的另一个屏幕上

componentDidMount = () => {
  
  const { navigation } = this.props;
  if (navigation.state.params && navigation.state.params.previous_screen) {

    this.setState({
      previous_screen: navigation.state.params.previous_screen
    });

  } else {
    console.log("ERROR");
  }
};

演示

函数版本

const goToScreen = () => {
  // assuming that navigation is passed in props
  props.navigation.navigate('Settings', {
    previous_screen: 'Home'
  })
}

并且可以像这样访问参数

const Settings = ({ route }) => {
  const { previous_screen } = route.params;

  return ....
}

它的功能版本可能有什么解决方案。 - Because i hate myself
逻辑是相同的,只需在参数中设置prev路由。 - Junius L

8
我找到了一种正确的方法,可以从当前屏幕中找到上一个路由(屏幕)的名称。
 props.navigation.dangerouslyGetParent().state.routes 

你可以从导航栈中获取屏幕列表(数组),例如:

输出结果如下:

Array(0) [, …]
0:Object {routeName: "ROUNTE_NAME", key: "id-158*****6785-1"}
1:Object {params: Object, routeName: "Screen1", key: "Screen1"}
2:Object {params: Object, routeName: "Screen2", key: "Screen2"}

谢谢大家 - 很酷 ;)


2

使用navigation ref,您可以访问根状态。
此代码块可帮助检查目标路由是否在嵌套的导航/路由内(currentRoute?.state?.index > -1 && currentRoute?.state?.routes) ? currentRoute?.state?.routes?.[currentRoute?.state?.index]

      const getRecentRoutes = ()=> {
        const rootState = navigationContainerRef.current?.getRootState();
        const routes = rootState?.routes;
        const previousRoute = routes?.[routes?.length - 2];
        const currentRoute = routes?.[routes?.length - 1];
        return {
          currentRoute: (currentRoute?.state?.index > -1 && currentRoute?.state?.routes) ? currentRoute?.state?.routes?.[currentRoute?.state?.index] : currentRoute,
          previousRoute: (previousRoute?.state?.index > -1 && previousRoute?.state?.routes) ? previousRoute?.state?.routes?.[previousRoute?.state?.index] : previousRoute,
        };
      };

1
我使用了以下方法。这可能不是最好的方法,但它确实有效。
let routes = this.props.navigation.dangerouslyGetState().routes[0].state.history;
for (let idx = routes.length - 1; idx >= 0; idx--) {
  if (routes[idx].type == 'route') {
    let route = routes[idx].key;
    this.props.navigation.navigate(route.substr(0, route.indexOf('-')));
    break;
  }
}

0

app.js | index.js 中定义一些函数。意味着初始屏幕。

setActiveScreen = (activeScreen) => { 
    const previousScreen = this.state.activeScreen
    this.setState({activeScreen: activeScreen, previousScreen: previousScreen})
  }
  goBackScreen = () => {
    this.setState({activeScreen: this.state.previousScreen});
  }

并将这些函数传递到导航屏幕

<Stack.Screen >   
{(props) => <ComponentScreen goBackScreen={this.goBackScreen} setActiveScreen={this.setActiveScreen} /> }
</Stack.Screen>

然后在使用 navigation.goBack() 前运行 goBackScreen 在屏幕中。
<TouchableOpacity onPress={() => {
this.props.goBackScreen()
this.props.navigation.goBack();
}}><Text>Click</Text> </TouchableOpacity>

注意:现在你可以在activeScreen中获取上一个屏幕的名称。这只是一个可能性的示例。你也可以尝试自己的想法。


或者您可以在参数中传递前一个屏幕

navigation.navigate("home", {params: {previousScreen: '{{pass the currentScreen name}}'

然后你可以通过console.log(this.props.route.params)获取下一个屏幕。


0
使用 react-navigation v5,您可以使用路由和索引递归导航状态以查找当前路由。一旦找到当前路由(一个没有任何子路由的对象),您可以从索引中减去1来获取上一个路由。
实现此功能的代码如下:
const getPreviousRouteFromState = (route: NavigationRoute) => {
  let checkRoute = null
  if (route.state && route.state.index > -1 && route.state.routes) {
    checkRoute = route.state.routes[route.state.index]
    if (checkRoute.state && checkRoute.state.routes) {
      return getPreviousRouteFromState(checkRoute)
    }
    const previousRouteIndex = route.state.index - 1
    if (previousRouteIndex > -1) {
      checkRoute = route.state.routes[previousRouteIndex]
    }
  }
  return checkRoute
}

这种策略有一些限制 - 由于堆栈的限制,它将在返回导航时返回当前路线。当切换堆栈时,它还会返回当前屏幕。


你把它用在哪里了?屏幕组件中的路由只有keynameparams键。没有state - Ryan Pergent
我是这样使用它的const navState = useNavigationState((state) => state) const prevRoute = getPreviousRouteFromState({ state: navState }) - Corey

0
const navigateAction = NavigationActions.navigate({
  routeName: 'Profile',
  action: NavigationActions.navigate({ routeName: 'Profile', params: { previous_screen: 'Home' } }),
});
this.props.navigation.dispatch(navigateAction);

9
请评论一下你在这里粘贴的代码,这段代码将如何回答OP的问题? - dbraillon
4
仅有代码的回答很少有帮助。请评论您的代码或详细说明为什么这是解决问题的方法。 - RyanNerd

0
const routes = navigation.getState()?.routes;

const prevRoute = routes[routes.length - 2];

if (prevRoute && prevRoute.name === 'previousScreen') {
          navigation.navigate('previousScreen');
} else {
          navigation.navigate('nextScreen');
        }
 

0
在我的一个项目中,我尝试使用索引和路由来获取先前的屏幕名称。
我使用的是 react-navigation 5.x 版本。
const { index, routes } = this.props.navigation.getState();
if( index && routes && routes[index-1].name){
 const previousScreenName = routes[index-1].name;
 ... code goes here
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接