React Native+Firebase中用AsyncStorage更新用户头像报错
React Native Expo项目更新用户头像时出现Promise拒绝错误
在基于Expo的React Native项目中,通过AsyncStorage存储登录用户会话,App.js中用状态管理会话,但在Profile页面尝试更新用户头像时,触发错误:Possible Unhandled Promise Rejection: TypeError: undefined is not a function。
相关代码
App.js
const AuthenticatedUserProvider = ({ children }) => { const [user, setUser] = useState(null); return ( <AuthenticatedUserContext.Provider value={{ user, setUser }}> {children} </AuthenticatedUserContext.Provider> ); }; function RootNavigator() { const auth = getAuth(); const { user, setUser } = useContext(AuthenticatedUserContext); const [sesiones, setSesiones] = useState(null); useEffect(() => { const storeData = async (user) => { try { await AsyncStorage.setItem("cookie", JSON.stringify(user)); } catch (e) {} }; const obtenerSesion = async () => { try { const session = await AsyncStorage.getItem("cookie"); setSesiones(JSON.parse(session)); } catch (e) {} }; if (user) { storeData(user); obtenerSesion(); } if (!user) { obtenerSesion(); } const unsubscribe = onAuthStateChanged(auth, async (authenticatedUser) => { authenticatedUser ? setUser(authenticatedUser) : setUser(null); }); return () => unsubscribe(); }, [user]); return ( <NavigationContainer> {user || sesiones ? <AppNavigation /> : <GuestNavigation />} </NavigationContainer> ); } export default function App() { return ( <> <AuthenticatedUserProvider> <RootNavigator /> </AuthenticatedUserProvider> <Toast /> </> ); }
Profile.js
const uploadImage = async (uri) => { setLoading(true); const imageBlob = []; const metadata = { contentType: "image/jpeg", }; const img = await fetch(uri); const blob = await img.blob(); const storage = getStorage(); const archivoRef = ref(storage, `avatar/${id()}`); uploadBytes(archivoRef, blob, metadata).then((snapshot) => { updatePhotoAvatar(snapshot.metadata.fullPath); }); }; const updatePhotoAvatar = async (imagePath) => { try { const storage = getStorage(); const archivoRef = ref(storage, imagePath); const imageUrl = await getDownloadURL(archivoRef); updateProfile(photoURLs, { photoURL: imageUrl });//错误触发行 setAvatar(imageUrl); setLoading(false); } catch (error) { console.log(error); } };
问题原因
错误核心是调用updateProfile时传入的第一个参数不符合要求:
updateProfile是Firebase Auth提供的方法,要求第一个参数是Firebase Auth实例化的用户对象(即auth.currentUser)- 当前代码传入的
photoURLs是从AsyncStorage中获取的序列化用户数据(JSON解析后的普通对象),该对象没有updateProfile所需的内部方法,因此触发undefined is not a function错误
解决方案
1. 正确传入Firebase Auth用户对象
在Profile.js中获取Auth实例,使用auth.currentUser作为updateProfile的第一个参数,同时同步更新AsyncStorage中的用户数据:
// 在Profile.js顶部获取Auth实例 const auth = getAuth(); const updatePhotoAvatar = async (imagePath) => { try { const storage = getStorage(); const archivoRef = ref(storage, imagePath); const imageUrl = await getDownloadURL(archivoRef); // 修正:传入auth.currentUser而非序列化的photoURLs await updateProfile(auth.currentUser, { photoURL: imageUrl }); setAvatar(imageUrl); setLoading(false); // 同步更新本地缓存的用户数据 const updatedUser = { ...auth.currentUser, photoURL: imageUrl }; await AsyncStorage.setItem("cookie", JSON.stringify(updatedUser)); } catch (error) { console.log("更新头像失败:", error); setLoading(false); } };
2. 统一异步逻辑风格并完善错误处理
将uploadImage中的.then()改为await,保持代码风格一致,同时覆盖所有异常场景:
const uploadImage = async (uri) => { setLoading(true); try { const metadata = { contentType: "image/jpeg", }; const img = await fetch(uri); const blob = await img.blob(); const storage = getStorage(); const archivoRef = ref(storage, `avatar/${id()}`); const snapshot = await uploadBytes(archivoRef, blob, metadata); await updatePhotoAvatar(snapshot.metadata.fullPath); } catch (error) { console.log("上传图片失败:", error); setLoading(false); } };
3. 优化App.js的会话同步逻辑
在App.js的obtenerSesion函数中处理session为null的情况,避免JSON解析报错,同时移除重复的会话获取逻辑:
const obtenerSesion = async () => { try { const session = await AsyncStorage.getItem("cookie"); setSesiones(session ? JSON.parse(session) : null); } catch (e) { console.log("获取会话失败:", e); setSesiones(null); } }; // useEffect内调整会话获取逻辑 useEffect(() => { // ... 其他函数定义 if (user) { storeData(user); // 移除重复的obtenerSesion调用,直接使用user状态即可 } else { obtenerSesion(); } // ... 其他逻辑 }, [user]);
内容的提问来源于stack exchange,提问作者yuu
相关产品推荐
相关产品推荐

