如何在react native中使用在另一个堆栈下面声明的堆栈导航器



我正试图将堆栈导航器放入另一个堆栈导航器中,如

const ProfileStack = createStackNavigator(
{
Profile: { screen: ProfileScreen },
Comment: { screen: CommentStack },
}
);
const CommentStack = createStackNavigator(
{
Comment: { screen: CommentScreen },
Profile: { screen: ProfileStack },
}
);

由于CommentStack是在ProfileStack之后声明的,所以我无法实现我想要的。有什么方法可以在react导航4中做同样的事情吗?

编辑:我正在尝试制作一个社交媒体应用程序,但以上方法不起作用。我目前的做法是:

const ProfileStack = createStackNavigator(
{
Profile: { screen: ProfileScreen },
Comment: { screen: CommentScreen },
}
);
const CommentStack = createStackNavigator(
{
Comment: { screen: CommentScreen },
Profile: { screen: ProfileStack },
}
);

但是,当有人访问某人的个人资料并对其帖子发表评论时,访问评论者的个人资料时,本地人会导航回个人资料屏幕。我想要的是发送到一个新的配置文件堆栈,这样它就可以循环工作对不起,英语不是我的第一语言

就像我在评论中提到的,你不能有两个导航器互相作为屏幕。您可以有一个以另一个导航器作为屏幕的导航器。但根据我从你的问题中了解到的情况,我认为甚至不需要ProfileStackCommentStack

相反,我建议使用一个导航器来保存CommentScreenProfileScreen,并让您的数据决定显示什么以及去哪里。这里有一些代码来说明我的意思:

/* The users in your system identified by an id 
and the comments they have on their profile */
const profileData = [
{
userId: 1,
comments: [
{ message: 'message from 2', commenter: 2 },
{ message: 'message from 3', commenter: 3 },
],
},
{
userId: 2,
comments: [{ message: 'message from 1', commenter: 1 }],
},
{
userId: 3,
comments: [{ message: 'message from 2', commenter: 2 }],
},
];
/* A simple profile screens that displays a user's profile
and that has a button to navigate to the comment page. */
const ProfileScreen = ({ navigation }) => {
const userId = navigation.getParam('userId');
return (
<View>
<Text>{`Profile of user ${userId}`}</Text>
<Button
title="go to comments"
onPress={() => {
navigation.push('Comment', { userId });
}}
/>
</View>
);
};
/* The comment screen shows all the comments a user has 
and displays a button next to a comment to go to that 
commenter's profile */
const CommentScreen = ({ navigation }) => {
const userId = navigation.getParam('userId');
return (
<View>
<Text>{`Comments of user ${userId}`}</Text>
{profileData
.filter((user) => user.userId == userId)[0]
.comments.map((comment) => {
return (
<View style={{ flexDirection: 'row' }}>
<Text>{comment.message}</Text>
<Button
title={`Go to ${comment.commenter}'s Profile'`}
onPress={() =>
navigation.push('Profile', { userId: comment.commenter })
}
/>
</View>
);
})}
</View>
);
};
// The screen you use to navigate to the profile screen
const InitialScreen = ({ navigation }) => {
return (
<View>
<Text>{`InitialScreen`}</Text>
<Button
title="Go to profile 1"
onPress={() =>
navigation.navigate('Profile', {
userId: 1,
})
}
/>
</View>
);
};
const ExampleNavigator = createStackNavigator({
Profile: { screen: ProfileScreen },
Comment: { screen: CommentScreen },
});
const MainNavigator = createStackNavigator(
{
SomeInitialScreen: { screen: InitialScreen },
ExampleNavigator: { screen: ExampleNavigator },
},
{
headerMode: 'none',
}
);
export default createAppContainer(MainNavigator);

因此,这里的想法是,您有一个数组来保存用户的数据,其中每个用户都可以通过一个id来识别,在本例中为userId。用户还可以具有comments属性,该属性保存来自评论者的message和评论者idcommenter

就导航而言,如果我们有权访问这种数据,实现这种结构,我们真正要做的唯一事情就是在导航到配置文件页面和导航到评论页面时传递userId


我在这个例子中添加了一个MainNavigator,因为根据这个问题,我假设在导航到特定用户的配置文件之前,您从另一个屏幕开始,比如主屏幕。

更新

OP表示,通过在按下导航按钮后禁用导航按钮,解决了重复屏幕错误。这绝对是一个简单而好的方法,但由于它可能对某人有所帮助,我也将解释如何在导航状态下防止重复。

这种情况下的重复意味着我们已经看到了一个特定的路由和userId的组合。我创建了一个函数,它取代了上一个例子中对push的调用:

function navigateByPushWithoutDuplicates(routeName, userId, navigation) {
const screenNavigatedToBefore = navigation
.dangerouslyGetParent()
.state.routes.find(
(element) =>
element.params.userId === userId && element.routeName === routeName
);
if (screenNavigatedToBefore !== undefined) {
const navigateAction = NavigationActions.navigate({
routeName: routeName,
params: { userId: userId },
key: screenNavigatedToBefore.key,
});
navigation.dispatch(navigateAction);
} else {
navigation.push(routeName, { userId: userId });
}
}

有了这个功能,你可以做这样的事情:

navigateByPushWithoutDuplicates("Comment", userId, navigation);

这个:

navigateByPushWithoutDuplicates("Profile", comment.commenter, navigation);

最新更新