[英]React rendering before async function finishes running
下面的程序從 Firebase 數據庫讀取數據,然后通過 setState 將其存儲到變量中。 在第一次渲染時,沒有 {problem} 是未定義的,因此不能在代碼中使用。 這意味着 React 只會渲染一個帶有硬編碼文本的頁面。 一旦 setState 運行,組件就會重新渲染,程序會顯示數據。 我唯一的問題是,當我將 {problem} 變量傳遞給子組件時,它返回以下錯誤(顯示的 AdditionalInfo.jsx 中的最后一行出現錯誤)。
AdditionalInfo.jsx:45 Uncaught TypeError: Cannot read properties of undefined (reading 'map')
為什么程序只返回子組件的錯誤,我該如何解決這個問題?
問題.jsx
const [problem, setProblem] = useState({});
useEffect(() => {
const getProblem = async () => {
const problemsRef = collection(db, "problems");
const q = query(problemsRef, where("problemNumber", "==", parseInt(params.id)));
const querySnapshot = await getDocs(q);
setProblem({...querySnapshot.docs[0].data()});
}
getProblem();
}, [params.id]);
.
.
.
return (
<Split
gutterSize={10}
gutterAlign="center"
cursor="col-resize"
snapOffset={75}
className='split'
minSize={0}>
<div className="bg-gray-100 min-h-screen max-h-screen overflow-y-auto"> {/* min-h-screen causes there to be a small scroll because of the navbar. To fix this use someting like min-h-screen minus height of navbar */}
<div className='mx-2 my-2 text-1xl font-medium'>
{problem.problemNumber}. {problem.problemTitle}
</div>
<div className='mx-2 my-2 text-1xl font-normal text-green-600'>
{problem.problemType}
</div>
<Divider variant="middle" />
<div className='mx-2 my-2 text-1xl text-base'>
{problem.problemQuestion}
</div>
<div>
{mapToArray(problem.companies).map(([key, value]) => {
return <CompanyTag key={key} companyName={value} companyId={key} />
}
)}
</div>
<AdditionalInfo problem={problem}/>
</div>
<div className="bg-gray-100">
<div className='mx-7'>
<video width="100%" height="100%px" controls>
<source src="movie.mp4" type="video/mp4"></source>
</video>
</div>
</div>
</Split>
)
附加信息.jsx
const AdditionalInfo = ({ problem }) => {
return (
<div>
{problem.questionTips.map((tip) => {
return <Tip key={tip.number} number={tip.number} description={tip.description} />
})} // Code causes an error here
.
.
.
作為答案來回答。
錯誤是由於您最初設置const [problem, setProblem] = useState({});
所以首先渲染你的問題只是一個空對象。 在您傳遞problem
的子組件中,您嘗試在 jsx 中使用 problem.questionTips.map() fn 並且由於第一次渲染問題。questionTips 未定義 - 嘗試在未定義時訪問 .map 會給您錯誤。
你應該使用?
運營商來解決這個問題。
{problem.questionTips?.map((tip) => {
return <Tip key={tip.number} number={tip.number} description={tip.description} />
})}
回答評論中的其他問題:“有沒有辦法完全等到在渲染之前從 firebase 讀取所有數據?”
是的,有一種方法,只需使用
{problem?.questionTips && <AdditionalInfo problem={problem}/>}
在加載questionTips
problem
,這不會呈現您的 AdditionalInfo 組件
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.