React Native集成Firebase谷歌登录时出现useMemo等错误求助
问题背景
我是React Native新手,用TypeScript开发应用并集成Firebase谷歌登录,在XCode模拟器构建模式下运行时触发以下错误:
ERROR Warning: Invalid hook call. Hooks can only be called inside of
the body of a function component. This could happen for one of the
following reasons:
- You might have mismatching versions of React and the renderer
(such as React DOM)- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app
ERROR TypeError: Cannot read property 'useMemo' of null, js engine:
hermesERROR 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.registerComponentwasn't called., js engine: hermes
我未使用useMemo Hook,试过Stack Overflow多种方案无效,相关代码如下:
index.ts
import { AppRegistry} from "react-native"; import { registerRootComponent } from "expo"; import App from "./App" AppRegistry.registerComponent("App", () => App); registerRootComponent(App);
App.tsx
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import LoginScreen from './src/components/LoginScreen'; import SignUpScreen from './src/components/SignUpScreen'; import ForgotPasswordScreen from './src/components/ForgotPassword'; import OtpScreen from './src/components/OtpScreen'; const Stack = createStackNavigator(); const App = () => { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Login"> <Stack.Screen name="Login" options={{headerShown: false}} component={LoginScreen} /> <Stack.Screen name="SignUp" options={{headerShown: false}} component={SignUpScreen} /> <Stack.Screen name="ForgotPassword" options={{headerShown: false}} component={ForgotPasswordScreen} /> <Stack.Screen name="OTP" options={{headerShown: false}} component={OtpScreen} /> </Stack.Navigator> </NavigationContainer> ); }; export default App;
LoginScreen.tsx
import React, { useState, useEffect } from 'react'; import { View, Text, TextInput, StyleSheet, Button, TouchableOpacity } from 'react-native'; import { promptAsync, request, response } from '../firebase/firebase.sign-in.util'; import { LinearGradient } from 'expo-linear-gradient'; import { GoogleAuthProvider, signInWithCredential } from 'firebase/auth'; import {auth} from '../firebase/firebase.util'; const LoginScreen = ({ navigation }: { navigation: any }) => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleLogin = () => { console.log('Login button pressed'); }; useEffect(()=>{ if(response?.type == "success"){ const {id_token} = response.params; const credential = GoogleAuthProvider.credential(id_token); signInWithCredential(auth, credential) } },[response]) return ( <LinearGradient colors={['#CACACA', '#053C4E']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={styles.container} > <Text style={styles.title}>Login</Text> <TextInput style={styles.input} placeholder="Email" placeholderTextColor="#f6f6f6" value={email} onChangeText={setEmail} /> <TextInput style={styles.input2} placeholder="Password" placeholderTextColor="#f6f6f6" secureTextEntry={true} value={password} onChangeText={setPassword} /> <TouchableOpacity onPress={() => navigation.navigate('ForgotPassword')}> <Text style={styles.forgotPassword} >Forgot Password ?</Text> </TouchableOpacity> <TouchableOpacity style={styles.loginButton} onPress={() => promptAsync()}> <Text style={styles.loginButtonText}>Login</Text> </TouchableOpacity> </LinearGradient> ); };
解决方案
1. 修复index.ts的重复注册问题
Expo项目中无需同时调用AppRegistry.registerComponent和registerRootComponent,二者会导致注册冲突,保留Expo官方推荐的registerRootComponent即可:
// 修改后的index.ts import { registerRootComponent } from "expo"; import App from "./App" registerRootComponent(App);
2. 排查firebase.sign-in.util的Hook误用
错误提示的useMemo为空,大概率是../firebase/firebase.sign-in.util文件中存在Hook违规调用(比如在函数组件外部使用useMemo、useState等),或依赖库版本不兼容:
- 检查该文件代码,确保所有Hook都在函数组件内部调用
- 锁定React与React Native的匹配版本,执行:
npm install react@18.2.0 react-native@0.72.0
3. 清理缓存并重启Metro
缓存异常会引发这类错误,执行以下命令清除缓存并重启服务:
# 清除Expo缓存 npx expo start --clear # 或清除Metro缓存 rm -rf node_modules/.cache
4. 检查重复的React副本
执行命令查看是否存在多版本React:
npm ls react
若输出多个版本,删除依赖文件后重新安装:
rm -rf node_modules package-lock.json npm install
5. 完善组件代码结构
确保LoginScreen组件标签完整闭合,避免渲染错误引发后续Hook调用异常。
内容的提问来源于stack exchange,提问作者Iseoluwa ariyibi

