skip to Main Content

Working on a problem from GreatFrontEnd that fetches data from a job api, first i have to fetch the ids, and then map over the ids to return an array of the job objects. I am having an issue where nothing will show up but when i change something minor in the code like deleting and adding back a parenthesis (which i believe simulates a re-render in the editor) the data will show up.

import React, { useState, useEffect } from 'react';

export default function App() {
  const [jobsIds, setJobIds] = useState(null);
  const [jobs, setJobs] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    getJobs();
    console.log(jobs)
}, []);

 

  const getJobIds = async () => {
     try {
      const idRes = await fetch(`https://hacker-news.firebaseio.com/v0/jobstories.json`);
      const jobIds = await idRes.json();
      setJobIds(jobIds);
    } catch (error) {
      console.error('Error fetching job IDs:', error);
    }
  }

  const getJobs = async () => {
    await getJobIds()
    
    try {
      setLoading(true);
      const jobsData = await Promise.all(
        jobsIds.map(async (id) => {
          const jobRes = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`);
          return await jobRes.json();
          
        })
       
      );
        setJobs(jobsData)
     
      setLoading(false);
    } catch (error) {
      console.error('Error fetching jobs:', error);
      setLoading(false);
    }
  };

  return (
    <>
    {loading? <p> Loading.... </p>: jobs.map((job) =>(
      <p> {job.title} </p>
  ))}
    </>
  );
}

`

Earlier i tried to put each fetch function in there own use effect hook and it worked, but I am trying to clean the code up and make it more concise.

2

Answers


  1. const getJobs = async () => {
        await getJobIds()
        
        try {
          setLoading(true);
          const jobsData = await Promise.all(
            jobsIds.map(
    

    This jobsId array you’re mapping over is the jobsIds array that existed when the component rendered. It does not include any values that resulted from calling getJobIds. You will need to change getJobIds to return the new ids, so you can map over them.

    const getJobIds = async () => {
         try {
          const idRes = await fetch(`https://hacker-news.firebaseio.com/v0/jobstories.json`);
          const jobIds = await idRes.json();
          setJobIds(jobIds);
          return jobIds; // <------- added
        } catch (error) {
          console.error('Error fetching job IDs:', error);
        }
      }
    
    const getJobs = async () => {
      const jobsIds = await getJobIds();
      // Same code, but now using the returned ids
    

    With this in place, you may not even need the jobsIds state. Feel free to delete it if it’s not being used anywhere.

    Login or Signup to reply.
  2. I am checking your code and fix the issue and update your code.
    kindly replace your code with this.

    import React, { useState, useEffect } from 'react';
    
    export default function App() {
      const [jobs, setJobs] = useState([]);
      const [loading, setLoading] = useState(false);
    
      useEffect(() => {
        getJobs();
        console.log(jobs)
    }, []);
    
     
    
      const getJobIds = async () => {
         try {
          const idRes = await fetch(`https://hacker-news.firebaseio.com/v0/jobstories.json`);
          const jobIds = await idRes.json();
          console.log('jobIds', jobIds); 
          return jobIds
        } catch (error) {
          console.error('Error fetching job IDs:', error);
        }
      }
    
      const getJobs = async () => {
        const jobIds = await getJobIds();
        if(jobIds){
          try {
            setLoading(true);
            const jobsData = await Promise.all(
              jobIds?.map(async (id) => {
                const jobRes = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`);
                return await jobRes.json();
                
              })
             
            );
              setJobs(jobsData)
           
            setLoading(false);
          } catch (error) {
            console.error('Error fetching jobs:', error);
            setLoading(false);
          }
        }
        
      };
    
      return (
        <>
        {loading? <p> Loading.... </p>: jobs?.map((job) =>(
          <p key={job?.id}> {job?.title} </p>
      ))}
        </>
      );
    }
    
    

    Note
    You set this setJobIds state at the same time and also call it on that same time.
    Second time data is coming because that time data are already set in state.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search