问题分析

在React Navigation从4+升级到7+后,出现The 'navigation' object hasn't been initialized yet错误,通常是由于在组件渲染时尝试访问未初始化的navigation对象。旧版Taro的跳转方法(如navigateTo)与新版React Navigation的API不兼容。

解决方法

重构路由跳转逻辑

将原有的Taro跳转方法(Taro.navigateToTaro.relaunchTaronavigateBack)替换为React Navigation 7+的API,并通过ROUTE_MAP统一管理路由名称,确保与dynamicRoutesname字段对应。(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页转场动效时长不足问题

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐