Search code examples
reactjsfetch-apiuse-effectuse-state

Why, despite pushing the elements, does my temp array contain no elements in the second useEffect?


I'm attempting to get the subtopics data, so first I have to get the courses in which a user has registered, then for each course I get the chapters, then for each chapter, I get the topics, and finally, I get the subtopics from each topic and push them all into the temp array. However, when I tried to print it in the second useEffect, it returned an empty array despite printing in the FetchSubtopics function.

import React from "react";
import { useEffect, useState } from "react";
import { useLocation, Link } from "react-router-dom";
import { baseURL } from "../../../Apis";
 
function Lectures() {

let temp = [];
const [courses, setcourses] = useState(()=> {return null});
 useEffect(() => {
 const fun = async (e) => {
  const response = await fetch(`${baseURL}/user/profile`, {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    },
  });
  const json = await response.json();
  if (json.success) {
    setcourses(json.data.courses);
  }
};
fun();
}, []);

if(courses){
  courses.map((course)=>{
  return FetchChapter(course._id);  
})
}

// Now fetching chapters of each course
function FetchChapter(id){
const fun = async (e) => {
const response = await fetch(`${baseURL}/course/${id}?queryParam=0`, {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${localStorage.getItem("token")}`,
  },
});
const json = await response.json();
json.data.chapters.map((chapter)=>{
  return FetchTopic(id,chapter._id);
});
 
};
fun();
}
 
function FetchTopic(id,chapter_id){
const fun = async (e) => {
const response = await fetch(`${baseURL}/course/${id}/? 
 queryParam=1&chapterID=${chapter_id}`, {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    },
  });
  const json = await response.json();
    json.data.chapter.topics.map((topics)=>{
          topics.subTopics.map((topic)=>{
            FetchSubtopic(topic)
          })
    });     
 }
 fun()
}

function FetchSubtopic(topic){
 const fun = async (e) => {
 const response = await fetch(`${baseURL}/course/subtopics/${topic._id}`, {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${localStorage.getItem("token")}`,
  },
 });
 const json = await response.json();
  if(json.contentType == 0){
    temp.push(topic);          // pushing all the subtopics into temp array
    console.log(temp);   
  }
  }
  fun()
  }

 const [State, setState] = useState([]);

useEffect(() => {
console.log(temp);  // Why empty?????
setState(temp);
}, []);

return (<> some code... </>)

}
export default Lectures;

Solution

  • I think you should call setState(temp) from inside fun rather than inside an useEffect.

    An useEffect with an empty array [] dependency is equivalent to componentDidMount.
    Hence it's called as soon as the component is mounted & does not wait for the fetch to complete.