React Native Paper Menu组件报错:Cannot read property 'level2' of undefined
问题场景
尝试在React Native项目的导航头部右侧添加React Native Paper的Menu组件,直接复制官方示例代码后运行,出现TypeError: Cannot read property 'level2' of undefined错误。
原代码
App.js
import { MD3LightTheme as DefaultTheme,PaperProvider } from 'react-native-paper'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import HomeScreen from './screens/Home/index'; import RegisterScreen from './screens/Register/index'; import ForgotPasswordScreen from './screens/ForgotPassword'; import SetPasswordScreen from './screens/SetPassword'; import DashboardScreen from './screens/Dashboard'; import HeaderMenu from './components/HeaderMenu'; const Stack = createNativeStackNavigator(); const theme = { ...DefaultTheme, // Specify custom property myOwnProperty: true, ...DefaultTheme.colors, // Specify custom property in nested object colors: { error: '#B22D1D', primary: '#0a4b7c', success: '#357a38' }, }; const headerMenuOptions = { headerRight: () => ( <HeaderMenu /> )} export default function App() { return ( <PaperProvider theme={theme}> <NavigationContainer> <Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" options={{headerShown:false}} component={HomeScreen} /> <Stack.Screen name="Register" component={RegisterScreen} /> <Stack.Screen name="ForgotPassword" component={ForgotPasswordScreen} /> <Stack.Screen name="SetPassword" component={SetPasswordScreen} /> <Stack.Screen name="Dashboard" options={headerMenuOptions} component={DashboardScreen} /> </Stack.Navigator> </NavigationContainer> </PaperProvider> ); }
HeaderMenu.js
import * as React from "react"; import { View } from "react-native"; import { Button, Menu, Divider, PaperProvider } from "react-native-paper"; function HeaderMenu() { const [visible, setVisible] = React.useState(true); const openMenu = () => setVisible(true); const closeMenu = () => setVisible(false); return ( <View style={{ }} > <Menu visible={visible} onDismiss={closeMenu} anchor={<Button onPress={openMenu}>Show menu</Button>} > <Menu.Item onPress={() => {}} title="Item 1" /> <Menu.Item onPress={() => {}} title="Item 2" /> <Divider /> <Menu.Item onPress={() => {}} title="Item 3" /> </Menu> </View> ); }; export default HeaderMenu;
错误信息
ERROR TypeError: Cannot read property 'level2' of undefined This error is located at: in Menu in ThemedComponent (created by withTheme(Menu)) in withTheme(Menu) (created by HeaderMenu) in RCTView (created by View) in View (created by HeaderMenu) in HeaderMenu (created by HeaderConfig) in RNSScreenStackHeaderSubview (created by ScreenStackHeaderRightView) in ScreenStackHeaderRightView (created by HeaderConfig) in RNSScreenStackHeaderConfig (created by HeaderConfig) in HeaderConfig (created by SceneView) in RNSScreen in Unknown (created by InnerScreen) in Suspender (created by Freeze) in Suspense (created by Freeze) in Freeze (created by DelayedFreeze) in DelayedFreeze (created by InnerScreen) in InnerScreen (created by Screen) in Screen (created by SceneView) in SceneView (created by NativeStackViewInner) in Suspender (created by Freeze) in Suspense (created by Freeze) in Freeze (created by DelayedFreeze) in DelayedFreeze (created by ScreenStack) in RNSScreenStack (created by ScreenStack) in ScreenStack (created by NativeStackViewInner) in NativeStackViewInner (created by NativeStackView) in RCTView (created by View) in View (created by SafeAreaInsetsContext) in SafeAreaProviderCompat (created by NativeStackView) in NativeStackView (created by NativeStackNavigator) in PreventRemoveProvider (created by NavigationContent) in NavigationContent in Unknown (created by NativeStackNavigator) in NativeStackNavigator (created by App) in EnsureSingleNavigator in BaseNavigationContainer in ThemeProvider in NavigationContainerInner (created by App) in ThemeProvider (created by PaperProvider) in RCTView (created by View) in View (created by Portal.Host) in Portal.Host (created by PaperProvider) in RNCSafeAreaProvider (created by SafeAreaProvider) in SafeAreaProvider (created by SafeAreaInsetsContext) in SafeAreaProviderCompat (created by PaperProvider) in PaperProvider (created by App) in App (created by withDevTools(App)) in withDevTools(App) in RCTView (created by View) in View (created by AppContainer) in RCTView (created by View) in View (created by AppContainer) in AppContainer in main(RootComponent), js engine: hermes WARN Possible Unhandled Promise Rejection (id: 7): TypeError: Cannot read property 'level2' of undefined TypeError: Cannot read property 'level2' of undefined
解决方案
1. 修复自定义主题结构
原主题代码错误地将DefaultTheme.colors展开到了主题的根层级,破坏了React Native Paper主题的原有结构,导致Menu组件无法读取到所需的level2样式属性。修改主题定义:
const theme = { ...DefaultTheme, myOwnProperty: true, colors: { ...DefaultTheme.colors, // 保留默认颜色,再覆盖自定义颜色 error: '#B22D1D', primary: '#0a4b7c', success: '#357a38' }, };
2. 移除HeaderMenu中多余的PaperProvider导入
顶层App.js已经用PaperProvider包裹了整个应用,子组件中无需重复导入和使用PaperProvider,否则会导致主题上下文冲突。修改HeaderMenu.js的导入部分:
import * as React from "react"; import { View } from "react-native"; import { Button, Menu, Divider } from "react-native-paper"; // 移除PaperProvider
3. 调整Menu初始可见状态
默认将Menu的visible设为false,符合菜单默认隐藏的交互逻辑:
const [visible, setVisible] = React.useState(false);
修改后的完整代码
修改后的App.js
import { MD3LightTheme as DefaultTheme,PaperProvider } from 'react-native-paper'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import HomeScreen from './screens/Home/index'; import RegisterScreen from './screens/Register/index'; import ForgotPasswordScreen from './screens/ForgotPassword'; import SetPasswordScreen from './screens/SetPassword'; import DashboardScreen from './screens/Dashboard'; import HeaderMenu from './components/HeaderMenu'; const Stack = createNativeStackNavigator(); const theme = { ...DefaultTheme, myOwnProperty: true, colors: { ...DefaultTheme.colors, error: '#B22D1D', primary: '#0a4b7c', success: '#357a38' }, }; const headerMenuOptions = { headerRight: () => ( <HeaderMenu /> ) } export default function App() { return ( <PaperProvider theme={theme}> <NavigationContainer> <Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" options={{headerShown:false}} component={HomeScreen} /> <Stack.Screen name="Register" component={RegisterScreen} /> <Stack.Screen name="ForgotPassword" component={ForgotPasswordScreen} /> <Stack.Screen name="SetPassword" component={SetPasswordScreen} /> <Stack.Screen name="Dashboard" options={headerMenuOptions} component={DashboardScreen} /> </Stack.Navigator> </NavigationContainer> </PaperProvider> ); }
修改后的HeaderMenu.js
import * as React from "react"; import { View } from "react-native"; import { Button, Menu, Divider } from "react-native-paper"; function HeaderMenu() { const [visible, setVisible] = React.useState(false); const openMenu = () => setVisible(true); const closeMenu = () => setVisible(false); return ( <View> <Menu visible={visible} onDismiss={closeMenu} anchor={<Button onPress={openMenu}>Show menu</Button>} > <Menu.Item onPress={() => {}} title="Item 1" /> <Menu.Item onPress={() => {}} title="Item 2" /> <Divider /> <Menu.Item onPress={() => {}} title="Item 3" /> </Menu> </View> ); }; export default HeaderMenu;
修复原理
- 主题结构错误是核心问题:React Native Paper的组件依赖主题中特定层级的样式定义,原代码破坏了主题结构,导致Menu组件无法读取
level2属性。 - 重复的PaperProvider会干扰主题上下文传递,导致子组件无法正确获取顶层主题。
- 初始可见状态设为
false符合常规菜单交互逻辑,避免组件加载时意外显示菜单。
内容的提问来源于stack exchange,提问作者Alaksandar Jesus Gene
相关产品推荐
相关产品推荐

