React+TypeScript中状态变量设置后渲染HTML的问题及解决
问题描述
我想在状态变量设置成功后渲染HTML块,定义了如下状态变量和赋值函数:
const formService:FormService=new FormService(); const [appointmentDate, setAppointmentDate] = useState<AppointmentDate>(); const [formattedDate, setFormattedDate ]=useState<string>() const [formattedTime, setFormattedTime ]=useState<string>() const [formattedTime20MinutesBefore, setFormattedTime20MinutesBefore] = useState<string>() useEffect(()=>{ init(); },[]) const init = async ()=>{ await getAppointmentData(); await organizeTheDates(); } const getAppointmentData = async ()=>{ const appointmentDateVar= await formService.getAppointmentPageInformation(3); setAppointmentDate(appointmentDateVar); } const organizeTheDates = async ()=>{ if (appointmentDate) { // 格式化时间日期并设置状态 const date:Date =(new Date(appointmentDate.dateTime)); setFormattedDate(`${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getFullYear()}`) setFormattedTime(`${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`) const twentyMinutesBefore = new Date(date.getTime() - 20 * 60000); setFormattedTime20MinutesBefore(`${twentyMinutesBefore.getHours().toString().padStart(2, '0')}:${twentyMinutesBefore.getMinutes().toString().padStart(2, '0')}`); } }
我通过以下判断控制页面渲染:
if(formattedDate != undefined && formattedTime != undefined ){ return ( /* 页面内容 */ ) }else { return <div>loading</div> }
但运行时页面一直停在loading状态,只有重新保存代码触发React重渲染后,才会正常显示页面。我猜测是useState的异步特性导致的问题,求解决方法。
更新
我根据Quentin的回答修改了部分代码:
const init = async ()=>{ await organizeTheDates(await getAppointmentData()); } const getAppointmentData = async ()=>{ const appointmentDateVar=await formService.getAppointmentPageInformation(3); setAppointmentDate(appointmentDateVar) return appointmentDateVar; }
解决思路与方案
问题核心:setAppointmentDate是异步操作,调用后appointmentDate状态不会立即更新。原代码中await getAppointmentData()仅等待接口请求完成,但此时appointmentDate还未更新,紧接着调用organizeTheDates()时,appointmentDate依然是undefined,导致格式化后的状态变量未被设置,页面一直停在loading。
最终修改方案
调整organizeTheDates函数,直接使用传入的接口返回数据,不再依赖状态变量:
// 修改organizeTheDates,接收接口返回的原始数据 const organizeTheDates = (appointmentDateVar: AppointmentDate) => { const date: Date = new Date(appointmentDateVar.dateTime); setFormattedDate(`${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getFullYear()}`); setFormattedTime(`${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`); const twentyMinutesBefore = new Date(date.getTime() - 20 * 60000); setFormattedTime20MinutesBefore(`${twentyMinutesBefore.getHours().toString().padStart(2, '0')}:${twentyMinutesBefore.getMinutes().toString().padStart(2, '0')}`); } // init函数保持修改后的逻辑 const init = async ()=>{ const appointmentData = await getAppointmentData(); organizeTheDates(appointmentData); }
简化方案(可选)
如果不需要保留appointmentDate状态,可直接在接口请求完成后处理格式化,彻底避免异步状态更新问题:
// 移除appointmentDate状态 const [formattedDate, setFormattedDate ]=useState<string>() const [formattedTime, setFormattedTime ]=useState<string>() const [formattedTime20MinutesBefore, setFormattedTime20MinutesBefore] = useState<string>() useEffect(()=>{ init(); },[]) const init = async ()=>{ const appointmentDateVar= await formService.getAppointmentPageInformation(3); const date: Date = new Date(appointmentDateVar.dateTime); setFormattedDate(`${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getFullYear()}`); setFormattedTime(`${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`); const twentyMinutesBefore = new Date(date.getTime() - 20 * 60000); setFormattedTime20MinutesBefore(`${twentyMinutesBefore.getHours().toString().padStart(2, '0')}:${twentyMinutesBefore.getMinutes().toString().padStart(2, '0')}`); }
内容的提问来源于stack exchange,提问作者marcus
相关产品推荐
相关产品推荐

