[英]Cannot import { getStorage } from firebase/storage to use with React Native Expo image picker
[英]Get image from expo image picker to users photoURL in firebase db
我的应用程序当前的问题是通过 firebase/expo 设置用户个人资料图片。 当用户最初登录时,他们被添加到我的 firestore 数据库“用户”中,uid 为 email 等。然后一旦他们登录/注册,我想在设置屏幕中实现一个功能来上传图片。 我有 expo 图像选择器库正常工作,但它不是登录用户独有的,如果用户注销/重新加载应用程序,它就会消失。 要以正确的方式实现这一点,我是否还必须另外使用 firebase 存储空间。 我是否必须将此添加到每个用户文档并添加图像:使用来自 expo 图像选择器的值?
**包含用于选择用户头像的设置页面的主仪表板/设置屏幕:
//imports
import React from 'react'
import { getStorage, ref, uploadBytes } from "firebase/storage";
import {db} from './firebase'
import { collection } from 'firebase/firestore';
import { doc,setDoc,updateDoc } from 'firebase/firestore';
import { StyleSheet, Text, View, SafeAreaView , Image, TextInput, Button,StatusBar,Modal,Pressable,Switch} from 'react-native';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import * as ImagePicker from 'expo-image-picker';
import { Platform } from 'react-native';
import { Feed } from './components/Feed';
import { Profile } from './components/Profile';
import { NavigationContainer } from '@react-navigation/native';
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { Notifications1 } from './components/Notifications1';
import {auth} from "./firebase"
import { Ionicons } from '@expo/vector-icons';
import { FontAwesome5 } from '@expo/vector-icons';
import { Entypo } from '@expo/vector-icons';
import { useState } from 'react';
import { MaterialIcons } from '@expo/vector-icons';
import { deleteUser } from "firebase/auth";
import { useEffect ,useRef} from 'react';
import { Appearance, useColorScheme } from 'react-native';
import Forums from "./components/Forums"
import { setStatusBarNetworkActivityIndicatorVisible } from 'expo-status-bar';
//tabs
const Tab = createMaterialBottomTabNavigator();
export const Login = ({setLoggedIn}) => {
//state
const currentUser = auth.currentUser;
const uid = currentUser.uid
const avatar = currentUser.photoURL
const [image, setImage] = useState("");
//functions
const pickImage = async () => {
try {
// No permissions request is necessary for launching the image library
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result);
if (!result.canceled) {
auth.currentUser.photoURL = result.uri
setImage(result.uri);
}
await updateDoc(doc(db, "users", uid, {
photoURL: result.uri.toString()
}))
}
catch(E) {
alert(E)
}
};
const storage = getStorage();
const storageRef = ref(storage, 'some-child');
// 'file' comes from the Blob or File API
uploadBytes(storageRef, file).then((snapshot) => {
console.log('Uploaded a blob or file!');
});
const username = auth.currentUser.email.replace(/@gmail.com/, '').replace(/@yahoo.com/, '').replace(/@aol.com/, '').toUpperCase()
const [modalVisible, setModalVisible] = useState(false);
const [isEnabled, setIsEnabled] = useState(false);
const toggleSwitch = () => {
setIsEnabled(previousState => !previousState)
colorScheme === "dark"
};
const user = auth.currentUser;
function deleteACC () {
deleteUser(user).then(() => {
setLoggedIn(false)
}).catch((error) => {
alert(error)
});
}
const colorScheme = useColorScheme();
useEffect(()=>{
const colorScheme = Appearance.getColorScheme();
if (colorScheme === 'dark') {
setIsEnabled(true); // true means dark
}else{
setIsEnabled(false); // false means light
}
registerForPushNotificationsAsync()
},[])
if (colorScheme === 'dark') {
} else {
// render some light thing
}
registerForPushNotificationsAsync = async () => {
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
};
return (
<View style={styles3.maincont}>
<StatusBar hidden />
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
setModalVisible(!modalVisible);
}}>
<View style={styles3.centeredView}>
<View style={styles3.modalView}>
<View style={styles3.modalview2}>
<Text style={styles3.modalText}>Settings:</Text>
<Text style={styles3.hi}>Hello, <Text style={styles3.helloUsername}>{username}</Text></Text>
<View style={styles3.imagemocont}>
<Button title="Pick an image from camera roll" onPress={pickImage} />
<Image source={{ uri: `${currentUser.photoURL ? currentUser.photoURL : "https://media.istockphoto.com/id/1248723171/vector/camera-photo-upload-icon-on-isolated-white-background-eps-10-vector.jpg?s=612x612&w=0&k=20&c=e-OBJ2jbB-W_vfEwNCip4PW4DqhHGXYMtC3K_mzOac0="}` }} style={{ width: 200, height: 200,borderRadius:500 }} />
</View>
</View>
<View style={{flexDirection:"row", alignItems:"center",marginBottom:15}}>
<Text style={{marginRight:20}}>Dark Mode:</Text>
<Switch
trackColor={{ false: "#767577", true: "#81b0ff" }}
thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"}
ios_backgroundColor="#3e3e3e"
onValueChange={toggleSwitch}
value={isEnabled}
/>
</View>
<View style={{width:"100%"}}>
<View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}}>
<Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}}>FAQ - POPULAR ASKED QUESTIONS</Text>
</View>
<View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}}>
<Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}}>Leave us a review </Text>
</View>
<View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}} >
<Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}} onPress={() => registerForPushNotificationsAsync()}>Notifications</Text>
</View>
<View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}}>
<Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}}>About us</Text>
</View>
</View>
<View style={{width:"100%"}}>
<View style={styles3.deleteacc}>
<Button onPress={(e) => deleteACC()} color="#fff" title="delete account" />
</View>
<View style={styles3.signout}>
<Button onPress={(e) => {setLoggedIn(false)}} color="#fff" title="sign out" />
</View>
<Pressable
style={[styles3.button, styles3.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}>
<Text style={styles3.textStyle}>Cancel</Text>
</Pressable>
</View>
</View>
</View>
</Modal>
<View style={styles3.logoCont}>
{/**
* <View style={{flexDirection: "row"}}>
<View style={styles3.logostco}>
<Image style={{height: 40,width:40}} source={{
uri: "https://cdn.discordapp.com/attachments/783336191529320498/1034953013695103017/Screen_Shot_2022-10-26_at_6.13.27_PM.png"
}}/>
</View>
<View style={styles3.eve2co}>
<Text style={styles3.logo}>EVENNTII</Text>
</View>
</View>
*/}
<View style={styles3.bottomcont}>
<View>
<Image source={{
uri:`${auth.currentUser.photoURL}`
}} style={{width:48,height:48,borderRadius:500,marginRight:10,borderColor:"#3A84EC",borderWidth:3}}/>
</View>
<Text style={styles3.username}>{username}</Text>
</View>
<Pressable style={[styles3.button, styles3.buttonOpen]} onPress={() => setModalVisible(true)}>
<Entypo name="dots-three-vertical" size={24} color="black" />
</Pressable>
</View>
<NavigationContainer
>
<Tab.Navigator
initialRouteName="Feed"
activeColor="#8DB7F3"
inactiveColor='#3A84EC'
barStyle={{ backgroundColor: '#fff' }}
>
<Tab.Screen
name="Feed"
component={Feed}
options={{
tabBarLabel: 'News',
tabBarIcon: ({ color }) => (
<Ionicons name="ios-newspaper-sharp" size={30} color={color} />
),
}}
/>
<Tab.Screen
name="Forums"
component={Forums}
options={{
tabBarLabel: 'Forums',
tabBarIcon: ({ color }) => (
<MaterialIcons name="forum" size={24} color={color} />
),
}}
/>
<Tab.Screen
name="Notifications"
component={Notifications1}
options={{
tabBarLabel: 'Crypto',
tabBarIcon: ({ color }) => (
<FontAwesome5 name="chart-area" size={26} color={color}/>
),
}}
/>
<Tab.Screen
name="Profile"
setParams={setLoggedIn}
component={Profile}
options={{
tabBarLabel: `NFT's`,
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="account" color={color} size={26} />
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
</View>
)
}
//push notifcations
async function schedulePushNotification() {
await Notifications.scheduleNotificationAsync({
content: {
title: "You've got mail! 📬",
body: 'Here is the notification body',
data: { data: 'goes here' },
},
trigger: { seconds: 2 },
});
}
async function registerForPushNotificationsAsync() {
let token;
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
token = (await Notifications.getExpoPushTokenAsync()).data;
console.log(token);
} else {
alert('Must use physical device for Push Notifications');
}
return token;
}
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
**火力基地配置:
import { initializeApp } from "firebase/app";
import { getAuth, createUserWithEmailAndPassword,signOut} from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import {REACT_APP_API_KEY} from '@env'
import { useEffect } from "react";
const firebaseConfig = {
apiKey: REACT_APP_API_KEY,
SECRET INFO}
const myApp = initializeApp(firebaseConfig);
export const auth = getAuth();
export const user = auth.currentUser;
export function createUser (auth, email, password) {
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
});
}
export default function signOutUser () {
signOut(auth).then(() => {
// Sign-out successful.
}).catch((error) => {
// An error happened.
});
}
export const db = getFirestore(myApp);
export const storage = getStorage(myApp);
**将用户添加到数据库的注册逻辑:
export const Main = ({setLoggedIn}) => {
// state
const [email, setEmail] = useState("")
const [slideim, setslideIm] =useState([])
const [password,setPassword] = useState("")
const [emaillo, setEmaillo] = useState("")
const [passwordlo,setPasswordlo] = useState("")
const [spim,setSpIm] = useState("")
const [modalVisible, setModalVisible] = useState(false);
const uid = auth.currentUser.uid
// functions for auth
const handleForm = () => {
createUserWithEmailAndPassword(auth, email, password)
.then(async (userCredential) => {
// Signed in
const user = userCredential.user;
try {
const docRef = await addDoc(collection(db, "users"), {
email:email,
password:password,
uid:uid
});
console.log("Document written with ID: ", docRef.id);
} catch (e) {
console.error("Error adding document: ", e);
}
//=================
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
alert(`a error occured ${errorCode}`)
});
}
const handleLogin = () => {
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
console.log(auth.settings)
// Signed in
const user = userCredential.user;
// ...
})
.catch((error) => {
alert(error)
});
}
const forgotPassword = async (email) => {
return sendPasswordResetEmail(auth, email).then((a) => {
alert("Password reset email sent")
}).catch(e => alert(e))
}
// coinbase open code
const [request, response, promptAsync] = useAuthRequest(
{
clientId: CLIENT_ID,
scopes: ["wallet:accounts:read"],
redirectUri,
},
discovery
);
const {
// The token will be auto exchanged after auth completes.
token,
exchangeError,
} = useAutoExchange(
response?.type === "success" ? response.params.code : null
);
React.useEffect(() => {
if (token) {
console.log("My Token:", token.accessToken);
}
}, [token]);
const { width, height } = Dimensions.get('window');
return (
<View style={styles2.overallCont}>
<StatusBar hidden />
{/** */}
{/**
* <View style={styles2.logoCont}>
<View style={styles2.logostco}>
<Text style={styles2.logostcote}>E</Text>
</View>
<Text style={styles2.logo}>EVENTEE</Text>
</View>
*/}
{/** */}
<View style={styles2.disimagco}>
<View>
<Image style={styles2.logoImage} source={{
uri:"https://cdn.discordapp.com/attachments/783336191529320498/1041428064955019324/Screen_Shot_2022-11-13_at_2.03.15_PM.png"
}}/>
</View>
</View>
<View style={styles2.bottom1}>
<Image source={{
uri:`https://cronuts.digital/wp-content/uploads/2022/01/5402207-scaled.jpg`
}} style={styles2.mainImage}/>
<View style={styles2.disTeCo}>
<Text style={styles2.disblu}>
Discover Rare NFT and Crypto Analytics
</Text>
{/** */}
</View>
{/** */}
<View style={styles2.signupCo}>
<View style={styles2.siteco}>
<Text style={styles2.maindesc}>NFTs and Crypto have exciting new properties: they’re unique, provably scarce, and usable across multiple applications.</Text>
</View>
<View style={styles2.teinpuco}>
<TextInput value={email} onChangeText={value => {setEmail(value)}} color="#fff" style={styles2.textinpu} placeholder="Enter your email..." autoCapitalize='none' placeholderTextColor="#EDEDED"/>
<TextInput value={password} onChangeText={value => {setPassword(value)}} placeholderTextColor="#EDEDED" color="#fff" style={styles2.textinpu} secureTextEntry autoCapitalize="none"
placeholder="Enter your password..."/>
<View style={styles2.buttonco}>
<Button onPress={handleLogin} color="white" title="Sign In" style={styles2.buttonsi} />
</View>
<View style={styles2.coinbasec}>
<Button title="Coinbase Connect"color="white" disabled={!request}
onPress={() => {
promptAsync();
}}/>
</View>
{/**
* <View style={{flexDirection:"row",alignItems:"center",justifyContent:"center"}}>
<Image style={{width:"70%",height:40,borderRadius:10,marginTop:10}} source={{
uri:"https://cdn.discordapp.com/attachments/783336191529320498/1037903445790826627/Screen_Shot_2022-11-03_at_9.37.38_PM.png"
}}/>
</View>
*/}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
setModalVisible(!modalVisible);
}}
>
<View style={styles2.modalView}>
<Image source={{
uri: "https://www.modernretail.co/wp-content/uploads/sites/5/2022/01/blockchain-explained-gif.gif"
}} style={{width: "100%",height: 380, position: "relative",bottom: 0,}}/>
<Text style={styles2.modalText}>Get Started</Text>
<View style={{
width: "100%"
}}>
<Text style={styles2.teinhe}>Email</Text>
<TextInput value={email} onChangeText={value => {setEmail(value)}} color="#fff" style={styles2.textinpu} placeholder="Enter your email..." autoCapitalize='none'/>
<Text style={styles2.teinhe}>Password</Text>
<TextInput value={password} onChangeText={value => {setPassword(value)}} color="#fff" style={styles2.textinpu} secureTextEntry autoCapitalize="none"
placeholder="Enter your password..."/>
<Text onPress={(email) => forgotPassword(email)} style={{textDecorationLine:"underline",color:"#fff",marginBottom:10}}>Forgot Password?</Text>
<View style={{
backgroundColor: "#4D76D8",
borderRadius: 10,
padding: 7
}} >
<Button type="submit" onPress={handleForm} color="white" title="Get Started" />
</View>
</View>
<Pressable
style={{
color: "white"
}}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles2.textStyle}>Cancel</Text>
</Pressable>
</View>
</Modal>
<Pressable
style={[styles2.button]}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles2.donthaveAcc}>Dont Have An Account?</Text>
</Pressable>
</View>
</View>
</View>
</View>
)
}
上面的代码给了我各种各样的错误,包括没有正确地将 expo 图像选择器库中的图像放入 firebase 中的用户文档。我该如何解决这个问题? **参考这段代码给我的问题最多:
await updateDoc(doc(db, "users", uid, {
photoURL: result.uri.toString()
}))
}
从图像选择器上传图像到谷歌云存储 -> 接收上传成功后返回的图像 Url -> 将其保存在 Firestore -> 需要时从 firestore 接收图像 url
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.