vue.js – Data is not coming if i use async in vue js 3

I am implementing Quiz App but here I am facing an issue if I put static data in array the questions are coming.

Data is not coming if i use async in Vue JS 3

But when get from the API the questions are not showing.

when I console the questions are showing in console and not showing in the front end.

For ref please find the attached code and image.

Home.vue (please see fetchQuestionsFromServer function)

     <template>
      <main class="flex h-screen items-center justify-center bg-gray-100">
        <!-- quiz container -->
          <QuizComplatePage v-if="endofQuiz" />
        <div
          class="overflow-hidden bg-white flex-none container relative shadow-lg rounded-lg px-12 py-6"
        >
          <img
            src="@/assets/images/abstract.svg"
            alt=""
            class="absolute -top-10 left-0 object-none"
          />
    
          <!-- contents -->
          <div class="relative z-20">
            <!-- score container -->
            <div class="text-right text-gray-800">
              <p class="text-sm leading-3">Score</p>
              <p class="font-bold">{{score}}</p>
            </div>
    
            <!-- timer container -->
            <div class="bg-white shadow-lg p-1 rounded-full w-full h-5 mt-4">
              <div class="bg-blue-700 rounded-full w-11/12 h-full" 
              :style= "`width: ${timer}%`"
              ></div>
            </div>
    
            <!-- question container -->
            <div
              class="rounded-lg bg-gray-100 p-2 neumorph-1 text-center font-bold text-gray-800 mt-8"
            >
              <div class="bg-white p-5">
               {{currentQuestion.question}}
              </div>
            </div>
    
            <!-- options container -->
    
            <div class="mt-8">
              <!-- option container -->
              <div v-for="(choice,item) in currentQuestion.choices" :key="item">
                <div
                class="neumorph-1 option-default bg-gray-100 p-2 rounded-lg mb-3 relative"
                :ref="optionchosen"
                @click="onOptionClick(choice,item)"
              >
                <div
                  class="bg-blue-700 p-1 transform rotate-45 rounded-md h-10 w-10 text-white font-bold absolute right-0 top-0 shadow-md"
                >
                  <p class="transform -rotate-45">+10</p>
                </div>
                <div class="rounded-lg font-bold flex p-2">
                  <!-- option ID -->
                  <div class="p-3 rounded-lg">{{item}}</div>
    
                  <!-- option name -->
                  <div class="flex items-center pl-6">{{choice}}</div>
                </div>
              </div>
              </div>
              <!-- option container -->
            </div>
    
            <!-- progress indicator container -->
            <div class="mt-8 text-center">
              <div class="h-1 w-12 bg-gray-800 rounded-full mx-auto"></div>
              <p class="font-bold text-gray-800">{{questionCounter}}/{{questions.length}}</p>
            </div>
          </div>
        </div>
      </main>
    </template>
    <script>
    import { onMounted, ref } from 'vue'
    import QuizComplatePage from './QuizCompleteOverlay.vue'
    export default{
      components: {
    QuizComplatePage
      },
      setup(){
        //data
        let canClick = true
        let score = ref(0)
        let timer = ref(100)
        let endofQuiz = ref(false)
        let questionCounter = ref(0)
        const currentQuestion = ref({
          question: '',
          answer: 1,
          choices: [],
        });
        const questions = []
    
    const loadQuestion = () =>{
      canClick = true
      timer.value=100
      //Check question array had questions or not
      if(questions.length > questionCounter.value){
         currentQuestion.value = questions[questionCounter.value]
         console.log('Current Question is : ', currentQuestion.value);
         questionCounter.value++
      }else{
        endofQuiz.value = true
        console.log('Out of Questions');
      }
     
    }
    
    
    //methods
    let itemsRef = []
    const optionchosen = (element) =>{
      if(element){
    itemsRef.push(element)
      }
    }
    
    const clearSelected = (divselected) =>{
      setTimeout(()=>{
      divselected.classList.remove('option-correct')
      divselected.classList.remove('option-wrong')
      divselected.classList.add('option-default')
      loadQuestion()
      },1000)
      
    }
    
    const onOptionClick = (choice,item) =>{
      if(canClick)
      {
        const divContainer = itemsRef[item]
      const optionId = item+1
      if(currentQuestion.value.answer ===optionId){
        console.log('You are Correct');
        score.value += 10
        divContainer.classList.add('option-correct')
        divContainer.classList.remove('option-default')
      }else{
        console.log('You are Wrong');
        divContainer.classList.add('option-wrong')
        divContainer.classList.remove('option-default')
      }
      timer.value=100
      canClick=false
      //to go next question
      clearSelected(divContainer)
      console.log(choice,item);
      }else{
        console.log('Cant Select Option');
      }
    }
    
    const countDownTimer = () =>{
    let interval= setInterval(()=>{
      if(timer.value>0){
        timer.value--
      }else{
        console.log('Time is over');
        clearInterval(interval)
      }
    
     },150)
    }
    
    const fetchQuestionsFromServer = async function(){
       fetch('https://opentdb.com/api.php?amount=10&category=18&type=multiple')
      .then((res) =>{
        return res.json()
      })
      .then((data) =>{
        const newQuestions = data.results.map((serverQuestion) =>{
          const arrangedQuestion = {
            question: serverQuestion.question,
            choices: '',
            answer: ''
            
          }
          const choices = serverQuestion.incorrect_answers
          arrangedQuestion.answer = Math.floor(Math.random() * 4 + 1)
          choices.splice(arrangedQuestion.answer-1 , 0 , serverQuestion.correct_answer)
          arrangedQuestion.choices = choices
          return arrangedQuestion
        })
        console.log('new formated questions' , newQuestions);
        questions.value = newQuestions
        loadQuestion()
        countDownTimer()
        console.log('questions: =>' , questions.value);
        
      })
    }
    
    
    //lifecycle hooks
    onMounted(() =>{
      fetchQuestionsFromServer()
    })
    
    
      //return
        return {
          timer,
          currentQuestion, 
          questions, 
          score,
          questionCounter, 
          loadQuestion,
          onOptionClick,
          optionchosen,
          endofQuiz,
          }
      }
    }
    </script>
    
     <style scoped>
    .neumorph-1 {
      box-shadow: 6px 6px 18px rgba(0, 0, 0, 0.09), -6px -6px 18px #ffffff;
    }
    .container {
      max-width: 400px;
      border-radius: 25px;
    }
    </style>

QuizComplatePage.vue

    <template>
      
      <div class="w-screen h-screen absolute z-30 bg-white bg-opacity-30 flex justify-center items-center">
    
        <div class="bg-green-700 p-4 text-center text-white">
            <p class="font-bold text-2xl">All DOne!</p>
            <p class="my-4 font-bold text-3xl">100% Score</p>
    
            <!-- Buttons -->
            <div class="flex justify-center">
                <div class="rounded-full py-1 w-28 border cursor-pointer hover:text-black hover:bg-white">Done</div>
                <div class="rounded-full py-1 w-28 border cursor-pointer hover:text-black hover:bg-white">Retry</div>
            </div>
        </div>
    
      </div>
    </template>
    
    <script>
    export default {
        name: 'QuizComplatePage'
    
    }
    </script>
    
    <style>
    
    </style>

Image.

Leave a Comment