在我的組件write-review.js中,我需要uid從當前登錄的用戶中提取 。
我有一個函式,FirebaseContext.js它創建一個身份驗證偵聽器并將身份驗證狀態設定為狀態,然后將該狀態轉換為背景關系,以便我可以在整個應用程式中使用它:
FirebaseContext.js
import { useState } from 'react'
import { auth } from "./firebaseConfig";
import { onAuthStateChanged } from 'firebase/auth';
import { createContext } from "react";
export const FirebaseContext = createContext()
const FirebaseContextProvider = (props) => {
const [activeUser, setActiveUser] = useState(null);
onAuthStateChanged(auth, (user) => {
if(user){
setActiveUser(user)
}else{
setActiveUser(null)
}
})
return (
<FirebaseContext.Provider value={{ activeUser }}>
{props.children}
</FirebaseContext.Provider>
);
};
export default FirebaseContextProvider
在我的write-review.js檔案中,我試圖uid退出我創建的身份驗證偵聽器背景關系。然而,這導致了一些奇怪的行為。
有時我可以破壞背景關系的 uid,如下所示:
const { activeUser } = useContext(FirebaseContext)
const {uid} = activeUser
console.log(uid) //yields the uid
但是有時我會遇到以下兩個錯誤之一:
1.
未捕獲的型別錯誤:無法解構“activeUser”的屬性“uid”,因為它為空。
警告:React 檢測到由 WriteReview 呼叫的 Hooks 的順序發生了變化。如果不修復,這將導致錯誤和錯誤。有關更多資訊,請閱讀 Hooks 規則:https ://reactjs.org/link/rules-of-hooks
我對為什么會發生這種情況感到困惑,因為在其他組件中我使用這個背景關系沒有問題。
關于如何以這種方式使用背景關系從登錄用戶中提取 uid 的任何想法?
專案結構大致如下:
src
|_components
| |_Header.js
|
|_pages
| |
| |_write-review.js
|
|_firebaseConfig.js
|
|_FirebaseContext.js
這是write-review.js組件:
import { useParams,useNavigate } from 'react-router-dom';
import { getAuth } from 'firebase/auth'
import { useState,useContext, useEffect } from 'react'
import { FirebaseContext } from '../FirebaseContext';
import { useVenues } from '../useVenue'
import { GetUsers } from '../useUser';
import { firebase,FieldValue } from '../firebaseConfig'
import Header from '../components/Header'
const WriteReview = () => {
const navigate = useNavigate()
const { activeUser } = useContext(FirebaseContext)
// const { userData } = GetUsers()
const [ {
title,
review,
rating,
ratingService,
ratingFood,
ratingValue,
ratingAtmosphere
}, setReview ] = useState({
title:'',
review:'',
rating:'',
ratingService:'',
ratingFood:'',
ratingValue:'',
ratingAtmosphere:'',})
let {id} = useParams()
const { venueData } = useVenues()
const filteredVenue = venueData.filter(item => {
return item.id === id
})
const handleChange = (e) => {
const { name,value } = e.target
e.preventDefault()
setReview(prevState => ({
...prevState,
[name]:value
}))
}
const handleSubmit = async (e) => {
const newReview = {
title:title,
review:review,
rating:rating,
ratingService: ratingService,
ratingFood: ratingFood,
ratingValue:ratingValue,
ratingAtmosphere:ratingAtmosphere
}
e.preventDefault()
await firebase
.firestore()
.collection('venues')
.doc(id)
.update({
reviews: FieldValue.arrayUnion(newReview)
})
navigate(`/venue/${id}`)
}
return(
<div>
<Header/>
<div className='write-review-top'>
{filteredVenue.map(venue => {
return(
<div className='write-review-top-img'>
<img src = {venue.photoUrl}/>
<div className='write-review-top-text'>
<p>{venue.name}</p>
<p>Venue address</p>
</div>
</div>
)
})}
</div>
<div className='write-review-form'>
<form onSubmit = {handleSubmit}>
<h2>Your first hand experiences helps other travellers!</h2>
<label>
Your overall rating of this venue <br></br>
<select name = 'rating' onChange = {handleChange}>
<option value = '1'>1</option>
<option value = '2'>2</option>
<option value = '3'>3</option>
<option value = '4'>4</option>
<option value = '5'>5</option>
</select>
</label>
<label>Title of your review <br></br>
<input type = 'text' name = 'title' value = {title} onChange = {handleChange}/>
</label>
<label >Your review <br></br>
<textarea type = 'text' name = 'review' value = {review} onChange = {handleChange}/>
</label>
<label>
Service <br></br>
<select name = 'ratingService' onChange = {handleChange}>
<option value = '1'>1</option>
<option value = '2'>2</option>
<option value = '3'>3</option>
<option value = '4'>4</option>
<option value = '5'>5</option>
</select>
</label>
<label>
Food <br></br>
<select name = 'ratingFood' onChange = {handleChange}>
<option value = '1'>1</option>
<option value = '2'>2</option>
<option value = '3'>3</option>
<option value = '4'>4</option>
<option value = '5'>5</option>
</select>
</label>
<label>
Value <br></br>
<select name = 'ratingValue' onChange = {handleChange}>
<option value = '1'>1</option>
<option value = '2'>2</option>
<option value = '3'>3</option>
<option value = '4'>4</option>
<option value = '5'>5</option>
</select>
</label>
<label>
Atmosphere <br></br>
<select name = 'ratingAtmosphere' onChange = {handleChange}>
<option value = '1'>1</option>
<option value = '2'>2</option>
<option value = '3'>3</option>
<option value = '4'>4</option>
<option value = '5'>5</option>
</select>
</label>
<button type = 'submit'>Submit</button>
</form>
</div>
</div>
)
}
export default WriteReview
uj5u.com熱心網友回復:
我懷疑當activeUser狀態設定為 null 時,您會看到錯誤。它肯定解釋了第一個錯誤Uncaught TypeError: Cannot destructure property 'uid' of 'activeUser' as it is null.:
const { activeUser } = useContext(FirebaseContext);
const { uid } = activeUser; // can't destructure from activeUser when null!
console.log(uid);
我的猜測是,當上述錯誤發生并被拋出時,組件中使用的其他 React 鉤子最終不會被呼叫,因此 React 框架中鉤子的整體順序發生了變化。
您可以提供一個備用值以從何時activeUser為空進行解構。
const { activeUser } = useContext(FirebaseContext);
const { uid } = activeUser || {}; // <-- provide fallback object to destructure from
console.log(uid); // value or undefined, but OK, won't throw error
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/425734.html
