为什么我的 useEffect 没有在渲染上运行?

问题描述 投票:0回答:1

在我的代码(React Native)中,为了避免“重新渲染次数过多”错误,我使用了 useEffect 钩子。我希望 useEffect 在组件 PracticeTest 首次运行时运行,但事实并非如此。有人可以解释一下我该如何解决它吗?

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”没有值。

javascript reactjs react-native
1个回答
0
投票

如果您不使用依赖项数组,则 useEffect 将在每个渲染上运行并且毫无用处。如果您只想在初始渲染时运行效果,则可以提供一个空数组作为依赖项数组: useEffect(() => {...}, [])

© www.soinside.com 2019 - 2024. All rights reserved.