React.js随机渲染数组:MCQ答题系统选项乱序实现方法
方案实现说明
现有代码可优化点
你写的Fisher-Yates洗牌算法本身逻辑是完全正确的,但是存在一个引用修改的问题:JS的数组是引用类型,你直接把mcqData.m_alternatives传入shuffle函数,会直接修改你导入的mcqContent原始数据,后续如果同一页面加载多道题、或者组件重复渲染时,会出现原始数据错乱的问题。
优化后可用代码
只需要修改两处:一是打乱前先对原选项数组做浅拷贝,避免修改原始数据;二是用useMemo缓存打乱后的数组,避免组件重复渲染时反复打乱选项(如果需要每次渲染都换顺序可以去掉useMemo)。
import React, { useMemo } from 'react'; import mcqContent from './mcq-content'; // 洗牌函数可以抽离到组件外复用 function shuffle(array) { // 先拷贝数组,不修改原数据 const shuffled = [...array] let currentIndex = shuffled.length, randomIndex; while (currentIndex !== 0) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; [shuffled[currentIndex], shuffled[randomIndex]] = [ shuffled[randomIndex], shuffled[currentIndex]]; } return shuffled; } const MCQPage = ({match}) =>{ const reqUrl = match.params.name; const mcqData = mcqContent.find(mcqData => mcqData.m_slug === reqUrl); // 提前存正确答案的逻辑和之前一致,没有问题 const correctMcq = mcqData.m_alternatives[0]; // 用useMemo缓存打乱后的选项,依赖为当前试题的slug,只有切换试题时才重新打乱 const shuffledArray = useMemo(() => { return shuffle(mcqData.m_alternatives) }, [mcqData.m_slug]) return ( <> <h1>{mcqData.m_title}</h1><br/> <h3>{mcqData.m_question}</h3> {shuffledArray.map((paragraph, key) => ( <p key={key}>{paragraph}</p> ))} <h4>Answer: {correctMcq}</h4> </> ); }; export default MCQPage;
迁移MongoDB兼容性说明
这套逻辑完全不需要调整,只要你从MongoDB查询返回的试题结构里,m_alternatives字段保持数组格式、m_slug字段作为URL匹配标识,就可以直接复用,不需要修改打乱相关的代码。
内容的提问来源于stack exchange,提问作者Aly
相关产品推荐
相关产品推荐

