[英]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.