如何在反应导航

时间:2018-04-14 01:05:08

标签: react-native react-navigation

目标

使用反应导航,从导航器中的屏幕导航到不同导航器中的屏幕。

更多详情

如果我有以下导航器结构:

  • 父导航器
    • 嵌套导航器1
      • 屏幕A
      • 屏幕B
    • 嵌套导航器2
      • 屏幕C
      • 屏幕D

如何从嵌套导航器2下的屏幕D转到嵌套导航器1下的屏幕A?现在,如果我尝试navigation.navigate从屏幕D屏蔽A,则会出现一个错误,表示它不知道屏幕A,只知道屏幕C和D.

我知道在本网站的各个地方以及GitHub(https://github.com/react-navigation/react-navigation/issues/983https://github.com/react-navigation/react-navigation/issues/335#issuecomment-280686611已经有各种形式的问题,但是对于那些基本的东西,缺乏明确的答案和滚动通过数百个GitHub评论搜索解决方案并不是很好。

也许这个问题可以为每个遇到这个常见问题的人编写如何做到这一点。

16 个答案:

答案 0 :(得分:19)

您可以使用third parameter of navigate来表示子操作。

例如,如果您想从嵌套导航器2下的屏幕D转到嵌套导航器1下的屏幕A:

this.props.navigation.navigate('NestedNavigator1', {}, NavigationActions.navigate({ routeName: 'screenB' }))

另外,如果您使用的是嵌套导航器,请务必查看v2文档中的Common mistakes部分。

答案 1 :(得分:19)

在React Navigation 5中,通过将屏幕作为第二个参数来传递,这变得更加容易:

navigation.navigate('Nested Navigator 2', { screen: 'screen D' });

如果屏幕嵌套很深,还可以包括其他级别:

navigation.navigate('Nested Navigator 2', {
    screen: 'Nested Navigator 3', params: {
        screen: 'screen E'
    }
});

答案 2 :(得分:7)

在React Navigation v5上,您具有所有解释:

https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator

路线定义

function Root() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Profile" component={Profile} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator>
        <Drawer.Screen name="Home" component={Home} />
        <Drawer.Screen name="Root" component={Root} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

说明

navigation.navigate('Root', { screen: 'Settings' });

答案 3 :(得分:5)

反应导航v3:

Navigation.navigate现在将一个对象作为参数。设置堆栈名称,然后按以下步骤导航到该堆栈中的路由...

navigation.navigate(NavigationActions.navigate({
    routeName: 'YOUR_STACK',
    action: NavigationActions.navigate({ routeName: 'YOUR_STACK-subRoute' })
}))

'YOUR_STACK'是创建堆栈时调用的堆栈...

  YOUR_STACK: createStackNavigator({ subRoute: ... })

答案 4 :(得分:3)

React Navigation v5 中,您可以执行以下操作:

lapply(list1, function(x) {
 x %>%
    mutate(date = lubridate::ymd_hms(date))  %>%
    arrange(order, date) %>%
    distinct(order, .keep_all = TRUE) %>%
    mutate(time_between = as.numeric(date - lag(date), units = 'hours'))
})

在上述情况下,您将导航到“媒体”屏幕,该屏幕位于嵌套在“声音”屏幕内的导航器中,位于嵌套在“设置”屏幕内的导航器中。

答案 5 :(得分:2)

@ZenVentzi,这是Nested Navigator 1具有Nested Navigator 1.1时多层嵌套导航器的答案。

  • 家长导航
    • 嵌套导航器1
      • 嵌套导航器1.1
        • 屏幕A
        • 屏幕B
    • 嵌套导航器2
      • 屏幕C
      • 屏幕D

我们可以根据需要注入NavigationActions.navigate()多次。

  const subNavigateAction = NavigationActions.navigate({
    routeName: 'NestedNavigator1.1',
    action: NavigationActions.navigate({
      routeName: 'ScreenB',
      params: {},
    }),
  });
  const navigateAction = NavigationActions.navigate({
    routeName: 'NestedNavigator1',
    action: subNavigateAction,
  });
  this.props.navigation.dispatch(navigateAction);

答案 6 :(得分:2)

尝试一下

Parent Navigator
  Nested Navigator 1
    screen A
    screen B
  Nested Navigator 2
    screen A
    screen C
    screen D

然后,就没有必要从D in 2转到A in 1,您只需从D in 2转到A中就可以了,可以在此处查看imageA stack navigator for each tab

答案 7 :(得分:1)

在 React Navigation v5 中

导航到堆栈上的特定屏幕

navigation.navigate('Home', {
   screen: 'Profile',
   params: {userID: 1}
 }
)

如果我们嵌套更多怎么办?

考虑这种结构:

NAVIGATOR:
  *StackA
    *ScreenC
    *ScreenD
  *StackB
    *ScreenI
    *StackE
      *ScreenF
      *StackG
        *ScreenJ
        *ScreenH

我们想从 StackA 中的 ScreenC 一直到 StackB 中的 ScreenH。 我们实际上可以将参数链接在一起以访问特定屏幕。

navigation.navigate('StackB',{
   screen: 'StackE',
   params: {
      screen: 'StackG',
      params: {
         screen: 'ScreenH'
      }
   }
  }
)

For more information

答案 8 :(得分:0)

在处理反应原生项目时,我遇到了同样的情况。我已尝试多种方式导航到屏幕但失败了。

经过多次试验,我尝试将父母导航对象传递给孩子并进行了导航功能调用,并且有效。

现在解决您的问题,如果您想从屏幕D导航到屏幕A,请执行以下步骤。

- &GT;使用screenProps将嵌套的导航器2导航道具传递给其子项。

export default class Home extends Component {
    static navigationOptions = {
        header:null
    };

    constructor(props) {
        super(props);
        this.state = {
            profileData: this.props.navigation.state.params,
            route_index: '',
        }
    }

    render() {
        return (
            <ParentNavigator screenProps={this.props.navigation} />
        );
    }
}

export const ParentNavigator = StackNavigator({
  // ScreenName : { screen : importedClassname }
  Nested1: { screen: nested1 },
  Nested2: { screen : nestes1 }
});

export const nested1 = StackNavigator({
  ScreenA: { screen: screenA },
  ScreenB: { screen : screenB }
});

export const nested2 = StackNavigator({
  ScreenC: { screen: screenC },
  ScreenD: { screen : screenD }
});

您可以使用

接收儿童导航
const {navigate} = this.props.screenProps.navigation;

现在这个navigate()可以用来在孩子之间导航。

我接受这个过程有点令人困惑,但我找不到任何解决方案,因此我必须完成我的要求。

答案 9 :(得分:0)

完全自由:单身,有navigationOptions

如果您有多个导航堆栈和子堆栈的情况,那么在如何设置React Navigation的情况下,如何知道如何获得所需堆栈的引用可能会令人沮丧。如果您能够在任何给定的时间简单地引用任何特定的堆栈,这将容易得多。就是这样。

  1. 创建一个特定于您要在任何地方引用的堆栈的单例。
    // drawerNavigator.js . (or stackWhatever.js)
    const nav = {}
    export default {
      setRef: ref => nav.ref = ref,
      getRef: () => nav.ref
    }

2。在堆栈的子屏幕上,获取对其props.navigation的引用

    import { createBottomTabNavigator } from 'react-navigation'
    import drawerNavigation from '../drawerNavigator'

    const TabNavigation = createBottomTabNavigator(
      {
        // screens listed here
      },
      {
        navigationOptions: ({ navigation }) => {
          // !!! secret sauce set a reference to parent
          drawerNavigation.setRef(navigation)
          return {
            // put navigation options
          }
        }
      }
    )

3。现在,您可以在内部或外部的任何地方引用drawerNavigator

    // screen.js
    import drawerNavigator from '../drawerNavigator'

    export default class Screen extends React.Component {
      render() {
        return (
          <View>
            <TouchableHighlight onPress={() => drawerNavigator.getRef().openDrawer()}>
              <Text>Open Drawer</Text>
            </TouchableHighlight>
          </View>
        )
      }
    }

说明

在步骤2中,“标签浏览器”是“抽屉浏览器”中的屏幕之一。 Tab Navigator需要关闭抽屉,但也需要关闭应用程序中的任何位置,执行此步骤后可以调用drawerNavigator.getRef().closeDrawer()

答案 10 :(得分:0)

我也找到了这样的解决方案here

onPress={() =>
    Promise.all([
    navigation.dispatch(
        NavigationActions.reset({
            index: 0,
            // TabNav is a TabNavigator nested in a StackNavigator
            actions: [NavigationActions.navigate({ routeName: 'TabNav' })]
        })
    )
    ]).then(() => navigation.navigate('specificScreen'))
}

答案 11 :(得分:0)

 const subAction = NavigationActions.navigate({ routeName: 'SignInScreen' });
      AsyncStorage.clear().then(() =>
        this.props.navigation.navigate('LoggedOut', {}, subAction));

LoggedOut是放置登录屏幕的堆栈名称。

答案 12 :(得分:0)

我的目标是使身份验证屏幕都具有相同的背景,并且使用常规堆栈转换来共享应用程序的其余部分。

几个小时后,我发现解决方案是将createStackNavigator()与组件包装器放在同一文件中。这样您就可以成功将document声明为static router。这样可以避免You should only render one navigator explicitly in your app警告,您可以使用this.props.navigation.navigate('AnyScreen')导航到任何嵌套屏幕。

AuthRouter.js

export const AuthNavigationStack = createStackNavigator(
  {
    Login: {
      screen: Login
    },
    CreateAccount: {
      screen: CreateAccount
    }
  }
);

export default class AuthContainer extends React.Component {
  constructor( props ) {
    super( props );
  }

  static router = AuthNavigationStack.router;

  render() {
    return (
      <ImageBackground
        style={ {
          width: '100%',
          height: '100%'
        } }
        source={ require( '../Images/johannes-andersson-yosimite.jpg' ) }
        blurRadius={ 10 }
      >
        <StatusBar
          barStyle="dark-content"
          backgroundColor="transparent"
          translucent={ true }
        />
        <AuthNavigationStack navigation={ this.props.navigation } />
      </ImageBackground>
    );
  }
}

MessengerRouter.js

export const MessengerStackNavigator = createStackNavigator(
  {
    Chat: {
      screen: Chat,
    },
    User: {
      screen: User,
    },
  }
);

export default class MainContainer extends React.Component {
  constructor( props ) {
    super( props );
  }

  static router = MessengerStackNavigator.router;

  render() {
    return <MessengerStackNavigator navigation={ this.props.navigation } />;
  }
}

Router.js

import { createStackNavigator } from 'react-navigation';

import AuthRouter from './AuthRouter';
import MessengerRouter from './MessengerRouter';

export const RootNavigationStack = createStackNavigator( {
  AuthContainer: {
    screen: AuthRouter,
    navigationOptions: () => ( {
      header: null
    } )
  },
  MessengerRouter: {
    screen: MessengerRouter,
    navigationOptions: () => ( {
      header: null
    } )
  }
} );

RootContainer.js

import { RootNavigationStack } from '../Config/Router';

class RootContainer extends Component {

  render() {
    return <RootNavigationStack />;
  }
}

注意:

  • header: null中的RootNaviagtionStack传递到嵌套堆栈中以删除重叠的标头

  • 如果您从嵌套A导航到嵌套B并使用“后退”按钮,它将使您返回到嵌套B中的第一个屏幕。这不是什么大问题,但我还没有弄清楚如何解决它。 / p>

答案 13 :(得分:0)

如果没有其他效果(例如我的情况),请执行以下操作:

Main / Root / App.js:

<StackNavigator ref={(x) => (global.stackNavigator = x)} />

任何地方:

global.stackNavigator.dispatch(
   NavigationActions.navigate({
       routeName: 'Player',
       params: { },
   }),
);

答案 14 :(得分:0)

在React Navigation V5中,您可以这样做:

但请记住,请将其放在父侧

this.props.navigation.navigate(
          'Nested Navigator 1',
          {name: 'jane'},
          this.props.navigation.navigate('Screen A', {id: 2219}),
        );

答案 15 :(得分:0)

这是另一种使用版本导航到嵌套屏幕的方法:5.x。它无需任何额外配置即可工作。更多信息请访问:https://reactnavigation.org/docs/use-link-to

const linkTo = useLinkTo();
// ...
// Just call this
linkTo(`/main/sub/subB`);