我不確定如何獲取上傳到 firebase 存儲的圖像 url 並將其保存到 firestore 數據庫。目前我有一個配置文件組件,用於存儲用戶將照片上傳到 firebase 存儲的邏輯。我有一個偵聽用戶更改的 UserContext 文件。以及創建用戶的 Firebase.utils。
Firebase.utils 文件:
import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import 'firebase/compat/auth';
import "firebase/compat/storage";
const config = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
firebase.initializeApp(config);
export const createUserProfileDocument = async (userAuth, additionalData) => {
// If user is not signed in do nothing
if (!userAuth) return;
const userRef = firestore.doc(`users/${userAuth.uid}`)
const snapShot = await userRef.get()
if (!snapShot.exists) {
// Added photoURL @@@
const { displayName, email, photoURL } = userAuth;
const createdAt = new Date();
try {
await userRef.set({
displayName,
email,
createdAt,
photoURL,
...additionalData
})
} catch (error) {
console.log('error creating user', error.message)
}
}
return userRef;
}
export const auth = firebase.auth();
export const firestore = firebase.firestore();
const storage = firebase.storage();;
export { storage, firebase as default };
import React, { useContext, useState, useEffect } from 'react';
import { auth, createUserProfileDocument } from "../Firebase/Firebase.utils";
const UserContext = React.createContext(null);
const UserUpdateContext = React.createContext();
const UserUpdateNameContext = React.createContext();
const UserUpdateEmailContext = React.createContext();
export const useUserContext = () => {
// useContext hook
return useContext(UserContext);
}
export const useUserContextUpdate = () => {
// useContext hook - toggleUser signout function
return useContext(UserUpdateContext)
}
export const useUserNameUpdate = () => {
// useContext hook - update user displayName
return useContext(UserUpdateNameContext)
}
export const useUserEmailUpdate = () => {
// useContext hook - update user email
return useContext(UserUpdateEmailContext)
}
export const UserContextProvider = ({ children }) => {
const [currentUser, setUser] = useState(null);
let unsubscribeFromAuth = null;
console.log(currentUser)
useEffect(() => {
unsubscribeFromAuth = auth.onAuthStateChanged(async userAuth => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
userRef.onSnapshot(snapShot => {
setUser({
id: snapShot.id,
...snapShot.data()
});
});
} else {
setUser(null)
// setUser({ currentUser: userAuth }) OBJECTS ARE TRUTHY
}
});
return () => {
unsubscribeFromAuth();
};
}, [])
console.log(unsubscribeFromAuth)
const toggleUser = () => {
auth.signOut()
.then(() => {
setUser(null)
})
.catch(e => console.log('There was a error:'(e)))
}
// console.log(currentUser)
// Get current window width
const useWindowWidth = () => {
const [width, setWidth] = useState(window.innerWidth)
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth)
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
})
return width
}
const width = useWindowWidth();
// Slice off end of displayName if reaches a certain length
const sliceDisplayName = (currentUser) => {
if (currentUser) {
const displayName = currentUser.displayName;
return (
width >= 1441 ? displayName.substring(0, 16) + '...'
: width <= 1440 && width >= 769 ? displayName.substring(0, 14) + '...'
: width <= 768 ? displayName.substring(0, 7) + '...'
: displayName
)
} else (console.log("No user found :("))
}
// console.log(sliceDisplayName(currentUser))
// Slice off end of email if reaches a certain length
const sliceEmail = (currentUser) => {
if (currentUser) {
const email = currentUser.email;
return (
width >= 1441 ? email.substring(0, 16) + '...'
: width <= 1440 && width >= 769 ? email.substring(0, 14) + '...'
: width <= 768 ? email.substring(0, 7) + '...'
: email
)
} else (console.log("No user found :("))
}
// console.log(sliceEmail(currentUser))
return (
<UserContext.Provider value={currentUser} >
<UserUpdateContext.Provider value={toggleUser} >
<UserUpdateNameContext.Provider value={sliceDisplayName} >
<UserUpdateEmailContext.Provider value={sliceEmail} >
{children}
</UserUpdateEmailContext.Provider >
</UserUpdateNameContext.Provider >
</UserUpdateContext.Provider >
</UserContext.Provider >
)
};
import React, { useState } from 'react';
import ReactTooltip from 'react-tooltip';
import { useUserContext, useUserContextUpdate, useUserNameUpdate } from '../../Utilities/Context/UserContext';
import { storage } from "../../Utilities/Firebase/Firebase.utils";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import ActivityFeed from '../../../src/components/ActivityFeed/ActivityFeed';
import Post from '../../../src/components/Post/Post';
import './Profile.css';
const Profile = ({ imageDate }) => {
const currentUser = useUserContext(); // Current user
const sliceDisplayName = useUserNameUpdate(); // Window width < (width) ? update displayName length
const [image, setImage] = useState("");
const [url, setUrl] = useState("");
// Listen for state changes, errors, and completion of the upload.
const handleUpload = () => {
const uploadTask = storage.ref(`images/${image.name}`).put(image);
uploadTask.on('state_changed',
(snapshot) => { console.log(snapshot) },
(error) => {
switch (error.code) {
case 'storage/unauthorized':
break;
case 'storage/canceled':
break;
case 'storage/unknown':
break;
}
},
(e) => {
storage
.ref("images")
.child(image.name)
.getDownloadURL(uploadTask.snapshot.ref)
.then(url => {
setUrl(url);
console.log('File available at', url);
})
}
);
}
console.log("image: ", image);
console.log(image.lastModifiedDate) // Image date uploaded. image.lastmodifiedDate === undefined ?
console.log(url)
const handleUploadChange = e => { // Maybe inside this function i can do the logic for recent activity and 0 photos +1
if (e.target.files[0]) {
setImage(e.target.files[0]);
}
};
return (
<div className="container-flex">
<div className="top-content-container w-100">
<div className="bot-content-wrapper px-1 py-2 mx-lg-auto d-flex flex-column flex-lg-row">
<div className="w-spacer profile-image-wrapper position-relative">
{
currentUser ?
<input
type="file"
for="Upload Image"
accept="image/*"
name="image"
id="file"
onChange={handleUploadChange}
onClick={handleUploadChange}
style={{ display: "none" }}
/>
: ''
}
<label for="file">
{
url.length <= 0 ?
<img
id='myimg'
className="profile-image-default profile-image d-block"
alt=""
/>
: currentUser ?
<>
<img
id='myimg'
className="profile-image d-block"
src={url}
alt=""
data-tip="Click me to update profile picture!" />
<ReactTooltip place="top" type="dark" effect="float" />
</>
:
<img
id='myimg'
className="profile-image-default profile-image d-block"
alt=""
/>
}
</label>
</div>
<div className="d-flex flex-column flex-lg-row align-items-lg-center w-lg-75 m-l-4">
<div className="d-flex flex-column flex-lg-row ml-auto pr-1 m-r-md-vw">
<div className="m-r-md">
<div className="d-flex flex-column w-100 m-r-6">
<div>
{
currentUser ?
<h2
data-tip={currentUser.displayName}>
{sliceDisplayName(currentUser)}
<span><ReactTooltip place="top" type="dark" effect="float" /></span>
</h2>
:
<h2>No User</h2>
}
</div>
<div className="d-flex flex-column flex-lg-row">
<div className="">
<i className="bi bi-people"></i>
<span className="banner-list-font mx-1">0 friends</span>
</div>
<div className="mx-lg-2">
<i className="bi bi-star"></i>
<span className="banner-list-font mx-1">0 reviews</span>
</div>
<div className="">
<i className="bi bi-camera"></i>
<span className="banner-list-font mx-1">0 photos</span>
</div>
</div>
</div>
</div>
<hr className=" d-lg-none" style={{ color: '#0a0a0a' }}></hr>
<div className="ml-3">
<div className="update-profile-wrapper grey-line-break d-flex flex-column m-l">
<div className="">
{
image.name !== undefined ?
<button
className="banner-list-font"
onClick={handleUpload}
// onClick={() => {
// handleUpload();
// forceUpdate();
// }}
>Add Profile Photo
</button>
: ''
}
</div>
<div className="">
<a className="banner-list-font" href='#'>Update Your Profile</a>
</div>
<div className="">
<a className="banner-list-font" href='#'>Find Friends</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="bot-content-container px-1 py-4 custom-padding">
<div className="bot-content-wrapper mx-lg-auto d-flex flex-column flex-lg-row">
<div className="sidebar d-flex flex-column mx-auto mx-lg-0 mt-lg-5 py-lg-2 px-2">
{
currentUser ?
<h4 className="mb-3">{currentUser.displayName}</h4>
:
<h4 className="mb-3">No User</h4>
}
<ul className="p-0">
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-person-badge"></i>
<h5 className="sidebar-list-font">Overview</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-person-plus"></i>
<h5 className="sidebar-list-font">Friends</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-award mx-1"></i>
<h5 className="sidebar-list-font">Reviews</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-lightbulb"></i>
<h5 className="sidebar-list-font">Tips</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-bookmark-star"></i>
<h5 className="sidebar-list-font">Bookmarks</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-bookmarks"></i>
<h5 className="sidebar-list-font">Collections</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-calendar-check"></i>
<h5 className="sidebar-list-font">Events</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
<a className="cursor-pointer text-decoration-none">
<li className="d-flex flex-row sidebar-item sidebar-list-font">
<i className="mx-2 bi bi-clock-history"></i>
<h5 className="sidebar-list-font">Order History</h5>
</li>
<hr style={{ color: '#0a0a0a' }}></hr>
</a>
</ul>
</div>
<div className="d-flex flex-column flex-lg-row w-100-md w-75-lg p-3 p-lg-0 m-l-4 pt-lg-3 pt-xl-4">
<div className="activity m-l-3">
<h3 className="heading-red">Notifications</h3>
<p className="font-14">No new friend requests or compliments at this time.</p>
<hr className="d-none d-lg-block" style={{ color: '#0a0a0a' }}></hr>
<h3 className="heading-red">Recent Activity</h3>
{<ActivityFeed />}
{<Post />}
</div>
<hr className="d-lg-none" style={{ color: '#0a0a0a' }}></hr>
<div className="grey-line-break ml-3">
<h3 className="heading-red mb-1 break-word">About
{
currentUser ?
<h3
data-tip={currentUser.displayName}
className="heading-red mb-1">
{sliceDisplayName(currentUser)}
<span><ReactTooltip place="top" type="dark" effect="float" /></span>
</h3>
:
<h3 className="heading-red mb-1">No User</h3>
}
</h3>
<h5 className="about-subHeading mt-2">Yelping Since</h5>
<p className="font-14">Some month</p>
<h5 className="about-subHeading mt-2">Things I Love</h5>
<p className="font-14">You haven't said yet...</p>
</div>
</div>
</div>
</div>
</div>
);
};
export default Profile;
import { createUserProfileDocument } from "../../Utilities/Firebase/Firebase.utils";
() => {
storage
.ref('images/')
.child(image.name)
.getDownloadURL(uploadTask.snapshot.ref)
.then(async (url, firestore, userAuth) => {
setUrl(url);
const userRef = firestore.doc(`users/${userAuth.uid}`)
await userRef.update({
photoURL: url
});
console.log('File available at', url);
})
}
import { storage, firestore } from "../../Utilities/Firebase/Firebase.utils";
() => {
storage
.ref('images/')
.child(image.name)
.getDownloadURL(uploadTask.snapshot.ref)
.then(async (url) => {
setUrl(url);
const userRef = firestore.doc(`users/${currentUser.id}`)
await userRef.update({
photoURL: url
});
console.log('File available at', url);
})
}
據我所知,您上傳圖像並在以下代碼段中獲取其下載 URL:
storage
.ref("images")
.child(image.name)
.getDownloadURL(uploadTask.snapshot.ref)
.then(url => {
setUrl(url);
console.log('File available at', url);
})
要將新 URL 寫入 Firestore 中用戶的個人資料文檔,請將其添加到then()
回調中:
const userRef = firestore.doc(`users/${userAuth.uid}`)
await userRef.update({
photoURL: url
});
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句