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

React简易韩语问答应用:useState/useEffect重复渲染等问题排查

React韩语问答应用问题排查与修复

问题1:控制台日志输出两次,首次为空

  • 原因:
    1. React开发环境的严格模式会触发组件双重渲染,用于检测潜在的副作用问题,这是正常机制。
    2. 组件初始化时randomOptions和question的初始值为空数组,首次渲染时状态还未被useEffect中的逻辑更新,因此日志显示空值;useEffect执行后状态更新,触发第二次渲染,日志才显示正确值。
  • 解决:
    • 开发环境的双重渲染无需额外处理,生产环境会自动消失。
    • 给question设置null作为初始值,避免首次渲染传递无效值给子组件。

问题2:randomOptions数组出现10个元素而非预期5个

  • 原因:
    1. 直接修改state数组:randomOptions.push()会修改原state数组,React要求状态不可变,直接修改会导致更新逻辑混乱。
    2. 多次异步更新状态:循环内反复调用setRandomOptions,但React状态更新是异步的,循环中randomOptions始终是初始空数组,导致后续排序和赋值逻辑出错。
    3. 引用赋值导致重复判断失效:previousArray = randomOptions是引用原数组,无法正确过滤重复值。
  • 解决:
    • 在函数内部创建临时数组,完成所有随机选择和排序后,一次性调用setRandomOptions更新状态。
    • 使用数组的不可变操作(如扩展运算符),避免直接修改原state数组。

问题3:引入
return (<Question/>)
组件触发错误,state值变为undefined

  • 原因:
    1. 初始question为空数组,传递给子组件后Data[answer]返回undefined,访问undefined.character会抛出错误。
    2. randomizeButtonAnswer中setQuestion(randomOptions[index])依赖异步更新的randomOptions,可能导致question被设置为undefined。
  • 解决:
    • 在Question组件中添加空值判断,避免访问无效属性。
    • 使用临时数组的索引设置question,确保值的有效性。

修正后的App.js

import './App.css';
import Data from './data/data.json';
import Header from './components/Header';
import Question from './components/Question';
import { useState, useEffect } from 'react';

function App() {
  const [index, setIndex] = useState(Math.floor(Math.random() * 5));
  const [randomOptions, setRandomOptions] = useState([]);
  const [question, setQuestion] = useState(null); // 初始设为null

  const randomizeButtonAnswer = () => {
    const newOptions = [];
    // 生成5个不重复的随机索引
    while (newOptions.length < 5) {
      const randomNumber = Math.floor(Math.random() * Data.length);
      if (!newOptions.includes(randomNumber)) {
        newOptions.push(randomNumber);
      }
    }
    // 打乱数组顺序
    const shuffledOptions = [...newOptions].sort(() => Math.random() - 0.5);
    setRandomOptions(shuffledOptions);
    // 从打乱后的数组中取对应index的元素作为正确答案
    setQuestion(shuffledOptions[index]);
  }
  
  useEffect(() => {
    randomizeButtonAnswer();
  }, [index])

  console.log('index is ' + index);
  console.log('randomOptions is ' + randomOptions);
  console.log('question is ' + question);

  return (
    <div className="App">
        <Header />
        {/* 只有当question有效时才渲染组件 */}
        {question !== null && <Question answer={question}/>}
    </div>
  );
}

export default App;

修正后的Question.js

import './Question.css';
import Data from '../data/data.json';

const Question = ({ answer }) => {
  // 空值判断,避免访问无效属性
  if (answer === null || !Data[answer]) {
    return <div className="question-wrapper">加载中...</div>;
  }

  return (
      <div className="question-wrapper">
          <h1 className="question"><span className="highlight">{Data[answer].character}</span></h1>
          <span>{Data[answer].character} = {Data[answer].char_id} </span>
      </div>
  );
}
 
export default Question;

内容的提问来源于stack exchange,提问作者SnooDucks299792

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:36:53