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

React Native:useEffect组件首次渲染未执行的问题排查与修复

问题:React Native中useEffect未执行导致数组为空

我在React Native代码中使用useEffect避免“Too many re-renders”错误,预期PracticeTest组件首次运行时useEffect会执行,但实际完全未运行,导致questionAnswers数组为空。已添加console.log验证useEffect未执行,寻求修复方法。

相关代码:

function PracticeTest({setCurrentMode}){
  const [index, setIndex] = useState(0);

  const [selected, setSelected] = useState(0);
  const [feedback, setFeedback] = useState('');
  const [score, setScore] = useState(0);
  
  // Create 'isCorrect' var to designate if ready to move on to the next question
  const [isCorrect, setIsCorrect] = useState(false);

  // get only the questions needed
  testQuestions = require('./testQuestions.json');
  let questionAnswers = [];

  let firstQuestionIndex;
  let lastQuestionIndex;
  let testLength = lastQuestionIndex - firstQuestionIndex;
  const [shuffled, setShuffled] = useState(false);

  const [done, setDone] = useState(false);



  
  useEffect(() => {
    questionAnswers = [];


    for(var i=0; i<testQuestions.length; i++){
      if((i>=firstQuestionIndex) && (i< lastQuestionIndex)){
        questionAnswers.push(testQuestions[i]);
        
      }
    }
      
      
      
    shuffle(questionAnswers);
      
    testLength = 10;
    shuffled = true;
    
  });
    

  // if quizType is "practiceTest" then the questions will be randomly selected and jumbled
  // Source for shuffle function (modified by me): https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
  function shuffle(array) {
    if(shuffled){
      console.log("ALREADY SHUFFLEDDDDDDDDDDDDDD");
    }
    else{
      
      let currentIndex = array.length;
    
      // While there remain elements to shuffle...
      while (currentIndex != 0) {
    
        // Pick a remaining element...
        let randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex--;
   
        // And swap it with the current element.
        [array[currentIndex], array[randomIndex]] = [
          array[randomIndex], array[currentIndex]];
      }
      console.log("Shuffle!!");
    }
  }
  
  

  let question = questionAnswers[index].question;


  function check(){
    if(selected == questionAnswers[index].correctID){
      // add 1 point to score if the feedback is blank
      if(feedback==''){
        setScore(score+1);
      }
      setFeedback('Correct!');
      setIsCorrect(true);
    }
    else{
      setFeedback("Try again");
    }
  }

  function proceed() {
    if((index + 1) >= testLength){
      // Code to be executed if done
      setDone(true);
    }
    else{
      setIndex(index + 1);
      setIsCorrect(false);
      setColor1('#FF6868');
      setColor2('#FF6868');
      setColor3('#FF6868');
      setColor4('#FF6868');
      setFeedback('');
    }
    
    
    
  }

  const [color1, setColor1] = useState('#FF6868');
  const [color2, setColor2] = useState('#FF6868');
  const [color3, setColor3] = useState('#FF6868');
  const [color4, setColor4] = useState('#FF6868');

  return (
    <View>
      {done ? 
        <QuizDone setCurrentMode={setCurrentMode} score={score} testLength={testLength}/>
      : 
        <View style={styles.app}>
          <Text style={styles.logo}>Testing your Knowledge</Text>
          <Text style={styles.question}>{question}</Text>
          <AnswerChoices setSelected={setSelected} index={index} questionAnswers={questionAnswers} color1={color1} color2={color2} color3={color3} color4={color4} setColor1={setColor1} setColor2={setColor2} setColor3={setColor3} setColor4={setColor4} />
          <BackButton setCurrentMode={setCurrentMode}></BackButton>
          {/** Feedback */}
          <View style={{
            position: 'absolute',
            width: 144,
            height: 42,
            top: 595,
            left: 63,
            justifyContent: 'center',
          }}>
            <Text>{feedback}</Text>
          </View>
          {/** Check Answer */}
          {
            isCorrect ? 
          <TouchableOpacity style={styles.checkButton} onPress={proceed}>
            <Text style={{color: 'white', alignSelf: 'center',}}>Move on</Text>
          </TouchableOpacity>
          :
          <TouchableOpacity style={styles.checkButton} onPress={check}>
            <Text style={{color: 'white', alignSelf: 'center',}}>Check</Text>
          </TouchableOpacity>
          }
        </View>
        }
    </View>
  )
}

我尝试添加console.log验证useEffect是否运行,但无输出,确认useEffect内代码未执行,导致questionAnswers数组无值。


修复方案

1. 给useEffect添加空依赖数组

当前useEffect未传递依赖数组,会导致它在每次组件渲染时都执行,但组件渲染时直接访问questionAnswers[index].question,此时数组为空会抛出错误,组件渲染失败,useEffect根本没机会执行。

给useEffect加上[]作为第二个参数,让它仅在组件挂载时执行一次:

useEffect(() => {
  // 你的逻辑
}, []);

2. 将questionAnswers、testLength转为状态变量

你使用普通变量let questionAnswers = []和let testLength,组件渲染时这些变量会被重新初始化,修改它们也不会触发组件更新。需要用useState转为状态:

// 替换原来的let声明
const [questionAnswers, setQuestionAnswers] = useState([]);
const [testLength, setTestLength] = useState(0);

在useEffect中更新状态:

useEffect(() => {
  const filteredQuestions = [];
  // 给first/lastQuestionIndex设置实际值,示例设为0和10
  const first = 0;
  const last = 10;
  for(let i=0; i<testQuestions.length; i++){
    if(i >= first && i < last){
      filteredQuestions.push(testQuestions[i]);
    }
  }
  
  // 直接在useEffect内处理洗牌逻辑
  const shuffledQuestions = [...filteredQuestions];
  let currentIndex = shuffledQuestions.length;
  while (currentIndex != 0) {
    let randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;
    [shuffledQuestions[currentIndex], shuffledQuestions[randomIndex]] = [
      shuffledQuestions[randomIndex], shuffledQuestions[currentIndex]];
  }
  
  setQuestionAnswers(shuffledQuestions);
  setTestLength(10);
  setShuffled(true);
}, []);

3. 初始化firstQuestionIndex和lastQuestionIndex

当前代码中这两个变量未赋值,会导致过滤条件i>=undefined永远为false,过滤不出任何问题。必须给它们设置具体初始值,比如从props传入或在useEffect内定义。

4. 避免直接修改状态变量shuffled

你在useEffect中直接写shuffled = true不会更新组件状态,必须用setShuffled(true)修改。

5. 防止数组为空时访问question

渲染question前先判断数组是否有数据,避免报错:

if (questionAnswers.length === 0) {
  return <Text>Loading...</Text>;
}
const question = questionAnswers[index].question;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:04:52