解决RN鸿蒙化 路由跳转Taro.navigate() 报The ‘navigation’ object hasn‘t been initialized yet的问题
·
问题分析
在React Navigation从4+升级到7+后,出现The 'navigation' object hasn't been initialized yet错误,通常是由于在组件渲染时尝试访问未初始化的navigation对象。旧版Taro的跳转方法(如navigateTo)与新版React Navigation的API不兼容。
解决方法
重构路由跳转逻辑
将原有的Taro跳转方法(Taro.navigateTo、Taro.relaunch、TaronavigateBack)替换为React Navigation 7+的API,并通过ROUTE_MAP统一管理路由名称,确保与dynamicRoutes的name字段对应。(dynamicRoutes是之前解决导航栏跳转定义的页面对象数组,可以看看我之前的文章)
// ROUTE_MAP.js
// 定义路由映射
const ROUTE_MAP = {
'pages/index/index': 'Index',
'pages/login/index': 'Login',
//...其他页面路由
}
export default ROUTE_MAP
// dynamicRoutes.js
// 定义路由映射
export const dynamicRoutes = [
{ name: 'Index' , path: () => require('../pages/index/index').default },
{ name: 'Login' , path: () => require('../pages/login/index').default },
//...其他页面路由
]
export default ROUTE_MAP
创建导航引用
在NavigationContainer创建一个全局导航引用
import { createNavigationContainerRef } from '@react-navigation/native';
// 创建全局导航引用
export const navigationRef = createNavigationContainerRef();
// 导航工具函数
export function navigate(name, params) {
if (navigationRef.isReady()) {
navigationRef.navigate(name, params);
} else {
setTimeout(() => navigate(name, params), 100);
}
}
render() {
return <NavigationContainer ref={navigationRef}>
//...页面
</NavigationContainer>
}
封装导航方法
准备好之后就可以创建统一的导航工具函数,替代原有的Taro方法
//navigationBridge.ts
//处理url参数方法
function parseQueryString(queryString?: string) {
const params: Record<string, string> = {};
if (queryString) {
queryString.split('&').forEach(pair => {
const [key, value] = pair.split('=');
if (key) params[key] = value ? decodeURIComponent(value) : '';
});
}
return params;
}
taroNavigateTo
export function taroNavigateTo(options: { url: string }) {
if (!options?.url) return;
// 分割路径和参数
const [path, queryString] = options.url.split('?');
const routeName = ROUTE_MAP[path];
if (routeName) {
const params = parseQueryString(queryString);
navigate(routeName, params);
} else {
// 降级到 Taro 原生跳转
Taro.navigateTo(options);
}
}
taroReLaunch
export function taroReLaunch(options: { url: string }) {
if (!options?.url) return;
// 分割路径和参数
const [path, queryString] = options.url.split('?');
const routeName = ROUTE_MAP[path];
if (routeName && navigationRef.isReady()) {
const params = parseQueryString(queryString);
// 使用 reset 来清除整个导航栈并设置新的根路由
navigationRef.reset({
index: 0,
routes: [
{
name: routeName,
params: params
},
],
});
} else {
// 降级到 Taro 原生跳转
Taro.reLaunch(options);
}
}
taroNavigateBack
export function taroNavigateBack() {
if (navigationRef.isReady()) {
const canGoBack = navigationRef.current?.canGoBack();
if (canGoBack) {
navigationRef.current?.goBack();
return Promise.resolve({ errMsg: 'navigateBack:ok' });
} else {
navigationRef.reset({
index: 0,
routes: [{ name: 'Index' }],
});
return Promise.resolve({ errMsg: 'navigateBack:ok' });
}
} else {
// 降级到 Taro 原生跳转
return Taro.navigateBack();
}
}
直接将以前的Taro.navigateTo(),Taro.relaunch(),Taro.navigateBack()直接替换就可以跳转了
import { taroNavigateTo, taroReLaunch, taroNavigateBack } from '@utils'
taroNavigateTo({
url: 'pages/index/index?id='+ id
})
taroReLaunch({
url:"pages/index/index?loginType=1"
})
goBackHandle = () => {
taroNavigateBack()
}
这几个跳转方法可以和我上一篇文章的底部路由跳转配合使用:解决React-Native鸿蒙化上架AppGallery Tab页转场动效时长不足问题
更多推荐
所有评论(0)