假设在标签浏览器中有两个堆栈屏幕:
在配置文件屏幕中,堆栈中还推送了其他类型相同的屏幕(“配置文件”)(具有不同的参数)。现在,如果您位于“摄像机”屏幕中,请执行以下操作:
navigation.navigate("Profile", { screen: "Profile", params });
您将导航到“配置文件”屏幕,这些参数将被发送到堆栈中的最后一个屏幕。如果我想导航到传递参数的堆栈的根,该怎么办?我尝试过:
// In the profile screen
useEffect(() => {
if (navigation.canGoBack())
navigation.popToTop(); // Go back to the root of the stack
showParams(params);
}, [params])
但是,这样,“showParams”操作不会在根目录中执行,而且我也没有从“相机”屏幕直接导航到堆栈的根目录。我认为在导航之前,必须在“相机”屏幕中执行以下操作:
navigation.dispatch(
CommonActions.reset({
// some stuff
})
);
navigation.navigate("Profile", { screen: "Profile", params });
但是我找不到任何实现目标的方法。有任何想法吗?谢谢。
更新-我的导航系统
堆栈(这里定义了多个堆栈:“HomeStacks”,“SearchStacks”,“ProfileStacks” ...)
const Stack = createStackNavigator();
export function ProfileStacks() { <------ Over this stack I do .push()
return (
<Stack.Navigator
initialRouteName="Profile"
>
<Stack.Screen name="Profile" children={Profile} />
<Stack.Screen name="EditProfile" children={EditProfile} />
</Stack.Navigator>
);
}
...
底部标签导航器<Tab.Navigator>
<Tab.Screen
name="Camera"
component={CameraPlaceholder}
listeners={({ navigation }) => ({
tabPress: (event) => {
event.preventDefault();
navigation.navigate("CameraModal");
},
})}
/>
<Tab.Screen
name="Profile"
component={ProfileStacks}
/>
</Tab.Navigator>
根堆栈导航器(应用程序的主导航器)在此堆栈中,我实现了身份验证流程,并且还声明了一些额外的堆栈(仅用于外观目的)。
export default function RootNavigator(props) {
/*
This navigator is implemented using the
'Protected Routes' pattern
*/
const { isUserLoggedIn } = props;
const RootStack = createStackNavigator();
return (
<RootStack.Navigator>
{isUserLoggedIn ? (
<>
<RootStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
/>
<RootStack.Screen
name="CameraModal"
component={Camera}
/>
</>
) : (
<>
<RootStack.Screen name="SignIn" component={SignIn} />
<RootStack.Screen
name="SignUp"
component={SignUp}
/>
<RootStack.Screen
name="ForgotPassword"
component={ForgotPassword}
/>
</>
)}
</RootStack.Navigator>
);
我看到的相关问题How to reset a Stack in a different Tab using React Navigation 5.x
https://github.com/react-navigation/react-navigation/issues/6639
https://github.com/react-navigation/react-navigation/issues/8988
这是我的“个人资料”标签的导航数据
Object {
"key": "Profile-Ty4St1skrxoven-jkZUsx",
"name": "Profile",
"params": undefined,
"state": Object {
"index": 1,
"key": "stack-8nWDnwDJZRK8iDuJok7Hj",
"routeNames": Array [
"Profile",
"EditProfile",
],
"routes": Array [
Object {
"key": "Profile-m0GQkvNk5RjAhGABvOy9n",
"name": "Profile",
"params": undefined,
},
Object {
"key": "Profile-tZAEmSU0eEo1Nt7XC09t1",
"name": "Profile",
"params": Object {
"otherUserData": Object {
"username": "jeffbezos",
},
"post": null,
},
},
],
"stale": false,
"type": "stack",
},
},
],
"stale": false,
"type": "tab",
},
我只需要从应用程序的另一个选项卡的“配置文件”选项卡中的“配置文件”堆栈中弹出第二条路线,然后导航至此屏幕。 最佳答案
在研究了几个小时后,我找到了解决方案。它不是最好的,但它适用于我的用例,并且肯定适用于其他人的用例。
我试图实现的是重置堆栈浏览器中“配置文件”屏幕的路由,而堆栈浏览器又位于当前堆栈屏幕所在的标签导航器的另一个标签中。这听起来有些令人困惑,但基本上与上传照片时在instagram上发生的事情类似。
如果在Instagram中从主屏幕导航到其他用户的个人资料,然后将照片上传到您的帐户,您将看到如何从“发布照片”屏幕转到“主页”选项卡中堆栈导航器的根目录,提要。
在我的用例中,我正在做类似的事情,我可以从自己的个人资料导航到其他用户的个人资料,并且照片会在此屏幕上带有进度条的上传。
从一开始我就想到要使用navigation.popToTop(),但是我一直无法获得想要的结果,因为正如我之前在问题中提到的那样,所有参数(包含帖子)都丢失了。因此,我别无选择,只能在“发布照片”屏幕上模拟这种行为。
我遵循的步骤如下:
这是代码:
const resetProfileStackNavigator = () => {
const currentNavigationState = navigation.dangerouslyGetState();
// Find the bottom navigator
for (let i = 0; i < currentNavigationState?.routes?.length; i++) {
if (currentNavigationState.routes[i].name === "BottomTabNavigator") {
// Get its state
const bottomNavigationState = currentNavigationState.routes[i].state;
// Find the profile tab
for (let j = 0; j < bottomNavigationState?.routes?.length; j++) {
if (bottomNavigationState.routes[j].name === "Profile") {
// Get its state
const profileTabState = bottomNavigationState.routes[j].state;
// Get the key of the profile tab's stack navigator
var targetKey = profileTabState?.key;
var targetCurrentRoutes = profileTabState?.routes;
break;
}
}
break;
}
}
// Reset the profile tab's stack navigator if it exists and has more than one stacked screen
if (targetKey && targetCurrentRoutes?.length > 1) {
// Set a new size for its current routes array, which is faster than Array.splice to mutate
targetCurrentRoutes.length = 1; // This simulates the navigation.popToTop()
navigation.dispatch({
...CommonActions.reset({
routes: targetCurrentRoutes, // It is necessary to copy the existing root route, with the same key, to avoid the component unmounting
}),
target: targetKey,
});
}
}
/*
Maybe, the stack navigator of the profile tab exists and has changed from its initial state...
In this situation, we will have to find the key of this stack navigator, which is also
nested in the same tab navigator in which this stack screen is.
*/
resetProfileStackNavigator();
// Finally, navigate to the profile stack screen and pass the post as param
navigation.navigate("Profile", {
screen: "Profile",
params: {
post,
},
});
Pd:我知道有一些适用的重构,但是我更喜欢以这种方式显示代码,以便使我上面讨论的步骤清晰可见。如果已阅读此书的任何人设法将此代码段概括为一个
使用ES6的通用函数,请将其作为答案,因为它对我和其他用户非常有用。