React组件提前返回未加载状态?异步数据渲染问题求解
解决React组件异步数据渲染问题
问题根源
- 普通变量无法触发重渲染:你用
let elements = []存储渲染内容,异步请求完成后更新这个变量,但React不会监听普通JS变量的变化,所以组件不会重新渲染,新的内容永远不会显示。 - 初始判断逻辑错误:
elements初始是数组,if (elements)始终为真,组件一开始就返回空数组的渲染结构,不会进入"Not yet loaded"分支;而异步完成后更新elements也无法触发重渲染,导致数据加载后界面没变化。
修复方案
使用React的useState管理状态,useEffect处理异步请求,让数据变化能触发组件重渲染:
import { AuthContext } from "../../App"; import { useContext, useEffect, useState } from 'react'; import axios from 'axios'; export default function Assignments({ clicked }) { const { loggedIn } = useContext(AuthContext); // 用useState管理题目数据和加载状态 const [questions, setQuestions] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { // 定义异步请求函数 const fetchAssignments = async () => { if (!loggedIn) { setLoading(false); return; } try { setLoading(true); const result = await axios.get('http://localhost:2000/database/assignments'); const qids = result.data["assignments"]; const result2 = await axios.post('http://localhost:2000/database/questions', { assignments: qids }, { headers: {'Content-Type': 'Application/json' } }); const fetchedQuestions = result2.data["assignments"]; setQuestions(fetchedQuestions); } catch (err) { console.log(err); setQuestions([]); } finally { setLoading(false); } }; fetchAssignments(); }, [loggedIn]); // 依赖loggedIn,登录状态变化时重新请求 // 根据状态渲染不同内容 if (loading) { return <>Not yet loaded</>; } if (!questions.length) { return <>No assignments found</>; } return ( <div className="flex flex-col gap-y-4 mt-1.5"> {questions.map(assignment => ( <div key={assignment.qid} className="p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-700 dark:border-gray-700"> <a href={`/codeground/${assignment.qid}`}> <h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">{assignment.heading}</h5> </a> <p className="mb-3 font-normal text-gray-700 dark:text-gray-400">{assignment.description}</p> <a href={`/codeground/${assignment.qid}`} className="inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"> Open Assignment <svg className="w-3.5 h-3.5 ml-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 10"> <path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M1 5h12m0 0L9 1m4 4L9 9"/> </svg> </a> </div> ))} </div> ); }
关键修改点
- 状态管理:用
useState创建questions存储题目数据,loading标记加载状态,这两个状态变化时会自动触发组件重渲染。 - 异步请求放入useEffect:把异步请求逻辑放到
useEffect中,依赖loggedIn,确保登录状态变化时重新拉取数据;同时在请求开始、结束/失败时更新loading状态。 - 渲染逻辑优化:根据
loading状态显示加载提示,根据questions长度判断是否显示空状态,避免初始空数组的误渲染。 - 修复路由链接:把原来的
#改成/codeground/${assignment.qid},符合你的注释需求。
内容的提问来源于stack exchange,提问作者Alpha々 Reaper
相关产品推荐
相关产品推荐

