React quiz app中useState触发shuffleMcq导致选中选项与显示不一致如何解决
问题根因
React函数组件在state发生变化时(调用setOption更新选中值时)会触发整个组件重新渲染,即QuizTakePage函数会完整执行一遍。你现在把shuffleMcq(optionsArray)直接写在组件顶层,每次渲染都会重新执行一次打乱逻辑生成全新的选项顺序,页面渲染的选项位置变化后,radio的选中态按索引对应就会出现选中值和显示内容不一致的问题。
修复后的测验页面代码
import React, { useState, useEffect } from 'react'; import mcqContent from './mcq-content'; import shuffleMcq from '../components/shuffleMcq'; const QuizTakePage = ({match}) =>{ const mcqData = mcqContent.find(mcqData => mcqData._id === 1); const optionsArray = mcqData.m_alternatives; const optionsCorrect = mcqData.m_alternatives[0]; // 打乱后的数组存入state,仅初始化时执行一次打乱逻辑 const [shuffledArray, setShuffledArray] = useState(() => shuffleMcq(optionsArray)); const [option, setOption] = useState(); const handleSubmit = (e) =>{ e.preventDefault(); console.log(option); checkAnswer(option,optionsCorrect) } return( <> <h4>{mcqData.m_title}</h4> <form onSubmit={handleSubmit}><div className="radio"><table><tbody> {shuffledArray.map((paragraph, key) => ( <tr key={key}><td><label><input type="radio" name="selected_option" id={`option_${key}`} value={paragraph} onChange={(e)=> setOption(e.target.value)}/>{paragraph}</label></td></tr> ))} </tbody></table> <button type="submit">Check Answer</button> </div></form> </> ); }; export default QuizTakePage; function checkAnswer(optionVar, corr) { if(optionVar==null){ console.log('Select an Answer'); } if(optionVar === corr) { console.log('Answer is Correct'); } else{ console.log('Wrong Answer'); } }
额外修复了原代码中所有radio共用同一个id的问题,避免label点击触发选中出现异常。
拓展:支持切换题目时重新打乱
如果后续需要支持切换不同题目,当题目数据变化时自动重新打乱选项,可以添加以下逻辑:
// 监听题目数据变化,切换题目时重新打乱选项并清空之前的选中值 useEffect(() => { setShuffledArray(shuffleMcq(mcqData.m_alternatives)); setOption(undefined); }, [mcqData])
内容的提问来源于stack exchange,提问作者Aly
相关产品推荐
相关产品推荐

