iOS端Expo React Native应用expo-splash-screen模块缺失问题求助
问题:Expo React Native iOS端
expo-splash-screen模块报错及"main"未注册问题 错误现象
- 导入
expo-splash-screen时触发:ERROR Error: Cannot find native module 'ExpoSplashScreen', js engine: hermes - 偶尔触发:
Invariant Violation: "main" has not been registered. This can happen if: * Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project. * A module failed to load due to an error and "AppRegistry.registerComponent" wasn't called., js engine: hermes - 仅在iOS开发构建运行时出现,Android端正常。
用户代码实现
import React, { useEffect, useState } from 'react'; import { StatusBar } from 'expo-status-bar'; import { useFonts, Inter_400Regular, Inter_600SemiBold, Inter_700Bold, Inter_800ExtraBold, } from '@expo-google-fonts/inter'; import Loading from './src/components/Loading'; import { QueryClient, QueryClientProvider } from 'react-query'; import { NavigationContainer, NavigationProp, useNavigation, } from '@react-navigation/native'; import { DashboardRoutes } from './src/routes/DashboardRoutes'; import { AuthRoutes } from './src/routes/AuthRoutes'; import useAuthenticatedStore from '@stores/useAuthenticatedStore'; import { deleteToken, getToken, getUser } from '@storage/token'; import * as SplashScreen from 'expo-splash-screen'; import { AuthStackParamList } from 'src/types/types'; import { navigationRef } from './src/routes'; import Toast, { BaseToast, ErrorToast, SuccessToast, } from 'react-native-toast-message'; import { jwtDecode } from 'jwt-decode'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; const queryClient = new QueryClient(); const toastConfig = { success: (props: any) => ( <SuccessToast {...props} style={{ borderLeftColor: 'green' }} contentContainerStyle={{ paddingHorizontal: 15 }} text1Style={{ fontSize: 15, fontWeight: '400', }} /> ), error: (props: any) => ( <ErrorToast {...props} text1Style={{ fontSize: 17, }} text2Style={{ fontSize: 15, }} /> ), }; const AppNavigation = () => { const { isAuthenticated, setUser, setIsAuthenticated, setProfilePictureUrl } = useAuthenticatedStore(); console.log('isAuthenticated', isAuthenticated); let expiry: boolean | undefined; useEffect(() => { console.log('AppNavigation useEffect'); async function prepare() { const token = await getToken(); if (token) { expiry = await getUser(); } console.log('expiry', expiry); try { if (token) { console.log('token before me api call', token); const url = //apicall here; const res = await fetch(url, { method: 'GET', headers: { Accept: 'application/json', Authorization: `Bearer ${token.trim()}`, }, }); const data = await res.json(); console.log('data', data); setUser({ email: data.email, name: data.name, }); setProfilePictureUrl(data.profile_picture_url as string); setIsAuthenticated(true); } } catch (e) { if (token && expiry === true) { await deleteToken(); setUser(null); } } } prepare(); }, [isAuthenticated, expiry]); return null; }; export default function App() { const [isReady, setIsReady] = useState(false); const [fontsLoaded] = useFonts({ Inter_400Regular, Inter_600SemiBold, Inter_700Bold, Inter_800ExtraBold, }); const { user } = useAuthenticatedStore(); useEffect(() => { SplashScreen.preventAutoHideAsync().finally(() => setIsReady(true)); }, []); useEffect(() => { if (isReady && fontsLoaded) { SplashScreen.hideAsync(); } }, [isReady, fontsLoaded]); console.log('User', user); console.log('isReady', isReady); if (!isReady || !fontsLoaded) { return <Loading />; } return ( <QueryClientProvider client={queryClient}> <NavigationContainer ref={navigationRef}> <GestureHandlerRootView style={{ flex: 1 }}> <AppNavigation /> {user ? <DashboardRoutes /> : <AuthRoutes />} <Toast config={toastConfig} /> <StatusBar style="dark" translucent /> </GestureHandlerRootView> </NavigationContainer> </QueryClientProvider> ); }
解决方案
1. 修复expo-splash-screen模块缺失问题
- 重新安装依赖:
npx expo install expo-splash-screen - 检查
app.json/app.config.js中splash screen配置是否完整,示例:"splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }
2. 清理iOS构建缓存并重建
- 停止Metro服务,执行清理命令:
npx expo prebuild --clean rm -rf ios/build - 清除Metro缓存并重启:
npx expo start --clear - 重新构建iOS开发包:
npx expo run:ios
3. 解决"main"未注册问题
- 确保
App.tsx默认导出组件无前置错误,避免因未捕获异常导致AppRegistry.registerComponent未执行 - 优化
splash异步操作的错误处理,避免异常中断组件加载:useEffect(() => { async function prepareSplash() { try { await SplashScreen.preventAutoHideAsync(); } catch (e) { console.warn('Failed to prevent splash auto hide:', e); } finally { setIsReady(true); } } prepareSplash(); }, []);
4. 检查Hermes引擎兼容性
- 确认
app.json中iOS的Hermes配置正确:"ios": { "hermesEnabled": true } - 若问题持续,可临时禁用Hermes测试是否为引擎兼容问题:
"ios": { "hermesEnabled": false }
内容的提问来源于stack exchange,提问作者Waleed Taher
相关产品推荐
相关产品推荐

