React项目点击刷新切换问题时偶现页面崩溃空白,求技术排查
React项目刷新按钮偶尔崩溃问题修复
问题描述
开发一个React项目,功能为展示单个问题,点击刷新按钮切换问题内容。整体运行正常,但点击刷新按钮时偶尔会出现代码崩溃、页面空白的情况。
相关代码
import React from "react" import questionsData from '../questionsData.js' function Content(){ const [question, setQuestion] = React.useState({ heading:"", hints : [] }) const [refresh, setRefresh] = React.useState(0) React.useEffect(function(){ if(questionsData){ const randomNo = Math.floor(Math.random() * questionsData.length) + 1 let headinggg = questionsData[randomNo].heading let hintsss = questionsData[randomNo].hints setQuestion({ heading: headinggg, hints: hintsss }) }else{ document.write("loading") } },[refresh]) const sugg = question.hints.map((hint) => { return( <li>{hint}</li> ) }) function renderQuestion(){ setRefresh(refresh + 1) } return( <div className="content"> <div className="question"> <h4>{question.heading}</h4> <br /> <span>You should say:</span> <ul> {sugg} </ul> </div> <div className="action"> <div className="record"> <img src="images/211859_mic_icon.svg" alt="" /> </div> <div className="refresh" onClick={renderQuestion}> <img src="images/3994399_refresh_reload_repeat_rotate_sync_icon.svg" alt="" /> </div> </div> </div> ) } export default Content
错误截图


问题原因
崩溃核心原因是数组索引越界:
代码中随机数生成逻辑const randomNo = Math.floor(Math.random() * questionsData.length) + 1存在错误。数组索引从0开始,Math.random() * questionsData.length的取值范围是[0, questionsData.length),经Math.floor处理后最大值为questionsData.length - 1,再加1会得到questionsData.length,此时访问questionsData[randomNo]会返回undefined,后续读取heading和hints时会抛出错误,导致组件渲染失败、页面空白。
另外,document.write("loading")属于React不规范用法,会覆盖整个文档,也可能引发异常,建议用React状态管理加载状态替代。
修复方案
- 修正随机数生成逻辑:去掉多余的
+1,确保索引在合法范围内
const randomNo = Math.floor(Math.random() * questionsData.length)
- 替换
document.write为状态管理加载状态(可选优化)
// 添加加载状态 const [isLoading, setIsLoading] = React.useState(true) React.useEffect(function(){ if(questionsData){ const randomNo = Math.floor(Math.random() * questionsData.length) const selectedQuestion = questionsData[randomNo] || { heading: "", hints: [] } setQuestion(selectedQuestion) setIsLoading(false) }else{ setIsLoading(true) } },[refresh]) // 渲染时判断加载状态 if(isLoading) return <div>loading</div>
- 添加空值保护(可选):避免选中
undefined时出错
const selectedQuestion = questionsData[randomNo] || { heading: "", hints: [] } setQuestion(selectedQuestion)
修复后的完整代码示例:
import React from "react" import questionsData from '../questionsData.js' function Content(){ const [question, setQuestion] = React.useState({ heading:"", hints : [] }) const [refresh, setRefresh] = React.useState(0) const [isLoading, setIsLoading] = React.useState(true) React.useEffect(function(){ if(questionsData && questionsData.length > 0){ const randomNo = Math.floor(Math.random() * questionsData.length) const selectedQuestion = questionsData[randomNo] || { heading: "", hints: [] } setQuestion(selectedQuestion) setIsLoading(false) }else{ setIsLoading(true) } },[refresh]) const sugg = question.hints.map((hint, index) => { return <li key={index}>{hint}</li> }) function renderQuestion(){ setRefresh(prev => prev + 1) } if(isLoading) return <div>loading</div> return( <div className="content"> <div className="question"> <h4>{question.heading}</h4> <br /> <span>You should say:</span> <ul> {sugg} </ul> </div> <div className="action"> <div className="record"> <img src="images/211859_mic_icon.svg" alt="麦克风图标" /> </div> <div className="refresh" onClick={renderQuestion}> <img src="images/3994399_refresh_reload_repeat_rotate_sync_icon.svg" alt="刷新图标" /> </div> </div> </div> ) } export default Content
内容的提问来源于stack exchange,提问作者Veerpal Kaur
相关产品推荐
相关产品推荐

