You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 15:30:00