簡體   English   中英

在異步函數完成運行之前反應渲染

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM