發(fā)布于:2021-02-19 00:00:20
0
149
0
本教程演示如何在react應(yīng)用程序中使用hooks來更好地集成firebase身份驗(yàn)證和firestore數(shù)據(jù)獲取。在開始之前,對hooks、firebase身份驗(yàn)證和firestore有一個(gè)基本的了解是很有幫助的。最后,我們將構(gòu)建示例應(yīng)用程序中的一些hooks,Julienne.app。
監(jiān)視身份驗(yàn)證
使用hooks和context的組合可以方便地訪問React應(yīng)用程序中任何位置的用戶會話。我們可以將用戶會話存儲在context中,并將該context傳遞給子組件。然后,這些組件可以使用hooks訪問會話對象。
首先,創(chuàng)造我們的環(huán)境。
const userContext = React.createContext({
user: null,
})
我們?yōu)閏ontext提供一個(gè)包含空會話對象的默認(rèn)值。當(dāng)我們使用firebase監(jiān)視會話的更改時(shí),這將發(fā)生變化。
接下來,我們將創(chuàng)建一個(gè)hooks,允許我們訪問context。
export const useSession = () => {
const { user } = useContext(userContext)
return user
}
最后,讓我們創(chuàng)建一個(gè)hooks來監(jiān)視firebase身份驗(yàn)證狀態(tài)。這個(gè)hooks將創(chuàng)建一個(gè)狀態(tài),它使用一個(gè)useState
回調(diào)來確定用戶會話是否已經(jīng)存在?;卣{(diào)是一種只在第一次裝入組件時(shí)使用值初始化狀態(tài)的有用方法。
接下來,我們使用監(jiān)視身份驗(yàn)證更改的effect
。當(dāng)您使用多種firebase登錄方法之一觸發(fā)登錄(或注銷)時(shí),將使用當(dāng)前身份驗(yàn)證狀態(tài)調(diào)用onChange
函數(shù)。
最后,我們返回身份驗(yàn)證狀態(tài)。
export const useAuth = () => {
const [state, setState] = React.useState(() => { const user = firebase.auth().currentUser return { initializing: !user, user, } })
function onChange(user) {
setState({ initializing: false, user })
}
React.useEffect(() => {
// listen for auth state changes
const unsubscribe = firebase.auth().onAuthStateChanged(onChange)
// unsubscribe to the listener when unmounting
return () => unsubscribe()
}, [])
return state
}
然后,我們可以在應(yīng)用程序的頂層使用這個(gè)hooks,并使用context提供程序?qū)⒂脩魰捥峁┙o子組件。
function App() {
const { initializing, user } = useAuth()
if (initializing) {
returnLoading}
return ()
}
最后,在子組件中,我們可以使用hooks訪問用戶會話。
function UserProfile() {
const { user } = useSession() returnHello, {user.displayName}}
要真正登錄或注銷,根本不需要使用hooks。只需調(diào)用firebase.auth().signOut()
或事件處理程序中的各種登錄方法。
獲取文檔
hooks對于使用firestore監(jiān)視單個(gè)文檔查詢非常有用。在本例中,我們希望在提供id
時(shí)獲取配方。我們希望為我們的組件提供error
、loading
和recipe
狀態(tài)。
function useRecipe(id) {
// initialize our default state
const [error, setError] = React.useState(false) const [loading, setLoading] = React.useState(true) const [recipe, setRecipe] = React.useState(null)
// when the id attribute changes (including mount)
// subscribe to the recipe document and update
// our state when it changes.
useEffect(
() => {
const unsubscribe = firebase.firestore().collection('recipes') .doc(id).onSnapshot( doc => { setLoading(false) setRecipe(doc) }, err => { setError(err) } )
// returning the unsubscribe function will ensure that
// we unsubscribe from document changes when our id
// changes to a different value.
return () => unsubscribe()
},
[id]
)
return {
error,
loading,
recipe,
}
}
獲取集合
獲取一個(gè)集合非常相似,但是我們訂閱了一個(gè)文檔集合。
function useIngredients(id) {
const [error, setError] = React.useState(false)
const [loading, setLoading] = React.useState(true)
const [ingredients, setIngredients] = React.useState([])
useEffect(
() => {
const unsubscribe = firebase
.firestore()
.collection('recipes')
.doc(id)
.collection('ingredients') .onSnapshot( snapshot => { const ingredients = [] snapshot.forEach(doc => { ingredients.push(doc) }) setLoading(false) setIngredients(ingredients) }, err => { setError(err) } )
return () => unsubscribe()
},
[id]
)
return {
error,
loading,
ingredients,
}
}
如果您計(jì)劃在整個(gè)應(yīng)用程序中使用firebasehooks,我建議您檢查react firebasehooks。它提供了一些有用的幫助,允許我們重用上面編寫的一些邏輯。
作者介紹