You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native的useContext自定义hook中获取navigation导航属性

解决方案

问题根源

你无法在CommonProvider中直接使用导航方法的核心原因是自定义Provider的层级在导航容器上层:React Context仅支持自上而下传递,上层组件无法访问下层组件的Context值,所以直接调用useNavigation会抛出找不到导航上下文的错误。另外你当前hook/index.tsx中存在未匹配的</NavigationProvider>闭合标签,属于语法错误,调整时可先删除。

方案1:调整组件层级(推荐,符合React设计规范)

将所有需要使用导航能力的自定义Provider放到NavigationContainer内部,即可直接获取导航上下文:

第一步:修改hook/index.tsx的AppProvider结构

import React, { ReactNode } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { AuthProvider } from './auth';
import { CommonProvider } from './common';

interface AppProviderProps {
  children: ReactNode;
}

function AppProvider({ children }: AppProviderProps) {
  return (
    {/* 导航容器放在最外层 */}
    <NavigationContainer>
      <CommonProvider>
        <AuthProvider>
          {children}
        </AuthProvider>
      </CommonProvider>
    </NavigationContainer>
  );
}

export { AppProvider };

第二步:在CommonProvider中获取导航对象

直接通过NavigationContext获取导航实例即可,比useNavigation更适配Provider场景:

import React, { createContext, ReactNode, useContext, useState } from 'react';
import { Dispatch, SetStateAction } from 'react';
// 导入导航上下文
import { NavigationContext } from '@react-navigation/native';

type CommonContextData = {
  isLoading: boolean;
  setIsLoading: Dispatch<SetStateAction<boolean>>;
};

interface CommonProviderProps {
  children: ReactNode;
}

const CommonContext = createContext<CommonContextData>({} as CommonContextData);

function CommonProvider({ children }: CommonProviderProps) {
  const [isLoading, setIsLoading] = useState<boolean>(false);
  // 直接获取导航上下文
  const navigation = useContext(NavigationContext);

  // 测试调用导航方法
  const testNavigate = () => {
    navigation?.navigate('TargetScreen');
  }

  return (
    <CommonContext.Provider value={{ isLoading, setIsLoading }}>
      {children}
    </CommonContext.Provider>
  );
}

function useCommon(): CommonContextData {
  const context = useContext(CommonContext);
  return context;
}

export { CommonProvider, useCommon };

方案2:全局导航Ref(无需调整层级)

如果不想改动现有层级结构,可以通过全局绑定导航容器Ref的方式,在任意位置调用导航方法:

第一步:创建全局导航Ref文件src/utils/navigationRef.ts

import { createNavigationContainerRef, NavigationProp } from '@react-navigation/native';

// 替换为你自己的路由参数类型定义
type RootParamList = {
  Home: undefined;
  Login: undefined;
  // 其余路由自行补充
};

export const navigationRef = createNavigationContainerRef<NavigationProp<RootParamList>>();

// 封装通用跳转方法
export function navigate<T extends keyof RootParamList>(name: T, params?: RootParamList[T]) {
  if (navigationRef.isReady()) {
    navigationRef.navigate(name, params);
  }
}

第二步:将Ref绑定到导航容器

修改hook/index.tsx中的AppProvider:

import { navigationRef } from '@/utils/navigationRef';

function AppProvider({ children }: AppProviderProps) {
  return (
    <NavigationContainer ref={navigationRef}>
      <CommonProvider>
        <AuthProvider>
          {children}
        </AuthProvider>
      </CommonProvider>
    </NavigationContainer>
  );
}

第三步:在CommonProvider中直接调用导航方法

import { navigate } from '@/utils/navigationRef';

function CommonProvider({ children }: CommonProviderProps) {
  const [isLoading, setIsLoading] = useState<boolean>(false);

  // 直接调用封装好的跳转方法即可
  const testNavigate = () => {
    navigate('Login');
  }

  // 其余逻辑保持不变
}

内容的提问来源于stack exchange,提问作者Andersonfrfilho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 12:36:03