Как перемещаться между различными вложенными стеками в режиме реагирования
Цель
Используя интерактивную навигацию, перейдите с экрана в навигаторе к экрану в другом навигаторе.
Более детально
Если у меня есть следующая структура Navigator:
- Родительский навигатор
- Вложенный навигатор 1
- Вложенный навигатор 2
как мне перейти с экрана D под вложенным навигатором 2, на экран A под вложенным навигатором 1? Прямо сейчас, если я попытаюсь перейти на navigation.navigate
на экран A с экрана D, появится сообщение о том, что он не знает о экране A, только экран C и D.
Я знаю, что это было задано в различных формах в разных местах на этом сайте, а также в GitHub (https://github.com/react-navigation/react-navigation/issues/983, https://github.com/react- навигация/реакция-навигация/проблемы/335 # issuecomment-280686611), но для чего-то такого базового, есть отсутствие четких ответов и прокрутка сотен комментариев GitHub, ищущих решение, невелика.
Возможно, этот вопрос может кодифицировать, как это сделать для всех, кто сталкивается с этой очень распространенной проблемой.
Ответы
Ответ 1
Вы можете использовать третий параметр navigate
для определения подэтапов.
Например, если вы хотите перейти от экрана D во вложенном навигаторе 2 к экрану A во вложенном навигаторе 1:
this.props.navigation.navigate('NestedNavigator1', {}, NavigationActions.navigate({ routeName: 'screenB' }))
Также не забудьте проверить Распространенные ошибки, если вы используете вложенные навигаторы.
Ответ 2
Реагируйте Навигация v3:
Navigation.navigate
теперь принимает один объект в качестве параметра. Вы устанавливаете имя стека, затем переходите к маршруту внутри этого стека следующим образом...
navigation.navigate(NavigationActions.navigate({
routeName: 'YOUR_STACK',
action: NavigationActions.navigate({ routeName: 'YOUR_STACK-subRoute' })
}))
Где 'YOUR_STACK' - это то, что называется вашим стеком, когда вы его создаете...
YOUR_STACK: createStackNavigator({ subRoute: ... })
Ответ 3
Полная свобода: синглтон с навигацией
Если у вас есть ситуация, когда у вас есть несколько стеков навигации и вспомогательных стеков, может быть сложно узнать, как получить ссылку на нужный стек, учитывая настройку React Navigation. Если бы вы могли просто ссылаться на любой конкретный стек в любой момент времени, это было бы намного проще. Вот как.
-
Создайте синглтон, специфичный для стека, на который вы хотите сослаться где угодно.
// drawerNavigator.js . (or stackWhatever.js)
const nav = {}
export default {
setRef: ref => nav.ref = ref,
getRef: () => nav.ref
}
-
Установите ссылку на нужный навигатор, используя navigatorOptions
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
}
}
}
)
-
Теперь вы можете ссылаться на 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 является одним из экранов в Drawer Navigator. Навигатор по drawerNavigator.getRef().closeDrawer()
должен закрывать ящик, но также и в любом месте вашего приложения, после этого шага вы можете вызывать drawerNavigator.getRef().closeDrawer()
. Вы не ограничены тем, что имеете прямой доступ к props.navigation после этого шага.
Ответ 4
Во время работы над проектом, отвечающим за реакцию, я столкнулся с такой же ситуацией. Я пробовал несколько способов навигации по экрану, но не смог.
После многих испытаний я попытался передать родительский объект навигации детям и сделал вызов функции навигации, и он сработал.
Теперь приступим к вашим проблемам. Если вы хотите перейти с экрана D на экран A, выполните следующие действия.
→ Пропускать вложенные навигационные навигационные навигаторы 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() можно использовать для перемещения между дочерними элементами.
Я согласен с тем, что этот процесс немного запутан, но я не мог найти никаких решений, поэтому мне пришлось это сделать, поскольку я должен выполнить свое требование.
Ответ 5
Я нашел также такое решение здесь:
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'))
}
Ответ 6
const subAction = NavigationActions.navigate({ routeName: 'SignInScreen' });
AsyncStorage.clear().then(() =>
this.props.navigation.navigate('LoggedOut', {}, subAction));
LoggedOut
- это имя стека, в котором находится экран входа.
Ответ 7
Моя цель состояла в том, чтобы все экраны аутентификации имели общий фон и все остальное приложение, используя обычный переход в стек.
По прошествии нескольких часов я обнаружил, что решение заключается в том, чтобы createStackNavigator()
находился в том же файле, что и оболочка компонента. Так что вы можете успешно выставить static router
как указано в документе. Это позволит избежать You should only render one navigator explicitly in your app
предупреждении 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
во вложенные стеки, чтобы удалить перекрывающийся заголовок
-
Если вы перейдете от Nested A к Nested B и нажмете кнопку "Назад", вы вернетесь к первому экрану в Nested B. Не большая проблема, но я не понял, как это исправить.
Ответ 8
@ZenVentzi, вот ответ для многоуровневых вложенных навигаторов, когда Nested Navigator 1
имеет Nested Navigator 1.1
.
- Родительский навигатор
- Вложенный навигатор 1
- Вложенный Навигатор 2
Мы можем просто вводить 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);