0

so i am fetching data from an API on page load in reactJS

  useEffect(() => {
    fetch('https://xxxxx/getdata',{
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body:JSON.stringify({
        Action : "xxxx",
        OrganisationID : "xxx-1000",
      })
    })
       .then((res) => res.json())
       .then((json) => {
          setResponse(json)
          console.log(json)
          
      })
       .catch((err) => {
         console.log(err.message);
       });
  }, []);

The json returns me an array of 2 objects.

{
    "OrganisationJobPosts": [
        {
            "Languages": [
                "English",
                "Spanish"
            ],
            "Project_Type": "One-Time Project",
            "Description": "This job requires Java and Javascript developers",
            "Status": "open",
            "Proposal_Questions": [
                "question1?",
                "question2?"
            ],
            "Entity": "JOBPOST",
            "Organization_Name": "ABC Company",
            "Jobpost_ID": "JOBPOST-20220608-10",
            "Jobpost_Title": "Web Developer",
            "Organization_ID": "ORGANIZATION-1000",
            "Rates": "$20/hour",
            "Experience": "< 3 Years",
            "Created_Date": 20220608,
            "Location": "Singapore",
            "SK": "JOBPOST-20220608-10",
            "PK": "ORGANIZATION-1000",
            "Skill_Set": [
                "HTML",
                "Javascript"
            ]
        },
        {
            "Languages": [
                "English",
                "French"
            ],
            "Project_Type": "Ongoing Project",
            "Description": "This job requires DB design skills",
            "Status": "Closed",
            "Proposal_Questions": [
                "Question A?",
                "Question B?"
            ],
            "Entity": "JOBPOST",
            "Organization_Name": "ABC Company",
            "Jobpost_ID": "JOBPOST-20220608-11",
            "Jobpost_Title": "Database Developer",
            "Organization_ID": "ORGANIZATION-1000",
            "Rates": "$20/hour",
            "Experience": "< 3 Years",
            "test": [
                "test"
            ],
            "Created_Date": 20220610,
            "Location": "TBD",
            "SK": "JOBPOST-20220608-11",
            "PK": "ORGANIZATION-1000",
            "Skill_Set": [
                "DynaomDB",
                "GraphDB"
            ]
        }
    ]
}

I then tried looping through the said array

  <header className="headerTabContent">
    {(() => {
      for (var key in response) {
        if (response.hasOwnProperty(key)) {                
            const resultarray = response[key]
            console.log(resultarray)
            for (var i=0;i<=resultarray.length;i++) {
              return(<h1 className="heading" onClick={()=>navigate('/dashboard/hire/discover/job-post')}>{resultarray[i].Jobpost_ID}</h1>)
            }

        }
      }
    })()};
  </header>

As seen my array length is 2. But the loop always outputs only the first array object (Job ID JOBPOST-20220608-10) wheras the second array item (JOBPOST-20220608-11) is not output. I can confirm the size is correct because before the second for loop, I did a console log of the length and found 2 objects. Am I doing something wrong here ?

2 Answers 2

4

Inside your for you call return (1):

enter image description here

This ends the arrow function in (2), returning the <h1>.

What you want is to call .map instead:

  <header className="headerTabContent">
    {(() => {
      for (var key in response) {
        if (response.hasOwnProperty(key)) {                
            const resultarray = response[key]
            console.log(resultarray)
            return resultarray.map(r => (
              <h1 className="heading" onClick={()=>navigate('/dashboard/hire/discover/job-post')}>{r.Jobpost_ID}</h1>
            ));
        }
      }
    })()}
  </header>

Though that will only return the resultarray of the first property of response. To return all properties on all of response's keys, you'll have to nest .map calls (or .flatMap/.map) as shown below:

  <header className="headerTabContent">
    {Object.values(response).flatMap(resultarray => {                
       console.log(resultarray)
       return resultarray.map(r => (
         <h1 className="heading" onClick={()=>navigate('/dashboard/hire/discover/job-post')}>{r.Jobpost_ID}</h1>
       ));
     })}
  </header>

Demo below:

const jsonResponse = {
    "OrganisationJobPosts": [
        {
            "Languages": [
                "English",
                "Spanish"
            ],
            "Project_Type": "One-Time Project",
            "Description": "This job requires Java and Javascript developers",
            "Status": "open",
            "Proposal_Questions": [
                "question1?",
                "question2?"
            ],
            "Entity": "JOBPOST",
            "Organization_Name": "ABC Company",
            "Jobpost_ID": "JOBPOST-20220608-10",
            "Jobpost_Title": "Web Developer",
            "Organization_ID": "ORGANIZATION-1000",
            "Rates": "$20/hour",
            "Experience": "< 3 Years",
            "Created_Date": 20220608,
            "Location": "Singapore",
            "SK": "JOBPOST-20220608-10",
            "PK": "ORGANIZATION-1000",
            "Skill_Set": [
                "HTML",
                "Javascript"
            ]
        },
        {
            "Languages": [
                "English",
                "French"
            ],
            "Project_Type": "Ongoing Project",
            "Description": "This job requires DB design skills",
            "Status": "Closed",
            "Proposal_Questions": [
                "Question A?",
                "Question B?"
            ],
            "Entity": "JOBPOST",
            "Organization_Name": "ABC Company",
            "Jobpost_ID": "JOBPOST-20220608-11",
            "Jobpost_Title": "Database Developer",
            "Organization_ID": "ORGANIZATION-1000",
            "Rates": "$20/hour",
            "Experience": "< 3 Years",
            "test": [
                "test"
            ],
            "Created_Date": 20220610,
            "Location": "TBD",
            "SK": "JOBPOST-20220608-11",
            "PK": "ORGANIZATION-1000",
            "Skill_Set": [
                "DynaomDB",
                "GraphDB"
            ]
        }
    ]
};

function App() {
  const [response, setResponse] = React.useState({})
  React.useEffect(() => {
    // returning a promise isntead of calling fetch for demo purposes
    Promise.resolve(jsonResponse)
       .then((json) => {
          setResponse(json)
          console.log(json)
          
      })
       .catch((err) => {
         console.log(err.message);
       });
  }, []);
  
  return (
 <header className="headerTabContent">
    {(() => (
      Object.values(response).flatMap(resultarray => {                
        console.log(resultarray)
        return resultarray.map(r => (
          <h1 className="heading" onClick={()=>navigate('/dashboard/hire/discover/job-post')}>{r.Jobpost_ID}</h1>
        ));
      })
    ))()}
  </header>
  );
}


ReactDOM.createRoot(document.getElementById('app')).render(<App />);
<script type="text/javascript" src="//unpkg.com/react@18/umd/react.production.min.js"></script>
<script type="text/javascript" src="//unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<div id="app"></div>

Sign up to request clarification or add additional context in comments.

3 Comments

It's not really clear why that code has to be in an immediately-invoked function. Also I suspect the navigation won't work since you're not including the job-id in the URI.
The IIFE is used to perform some sort of short-circuiting due to the imperative approach. In the complete, .flatMap/.map solution, indeed, no IIFE is needed.
Yeah, I was just curious why you used it in your answer when it's not needed.
0

A slightly simpler way forward would be to have a small function that can map over the OrganisationJobPosts array and return all the ids which you can then, in turn, map over to create the heading elements you need.

I imagine that you also need to include the id in the navigation link too as this example shows. Slightly different from your code the onClick handler calls a separate function which extracts the id from the element's dataset, and then uses that in the string for the endpoint.

const { useState } = React;

function Example({ res }) {

  function getJobIds(res) {
    return res.OrganisationJobPosts.map(post => {
      return post.Jobpost_ID;
    });
  }

  function handleClick(e) {
    const { id } = e.target.dataset;
    const path = '/dashboard/hire/discover/job-post';
    // navigate(`${path}/${id}`);
    console.log(`${path}/${id}`);
  }

  return (
    <section>
      {getJobIds(res).map(id => {
        return (
          <h1
            data-id={id}
            className="heading"
            onClick={handleClick}
          >{id}
          </h1>
        );
      })}
    </section>
  );

}

const res={OrganisationJobPosts:[{Languages:["English","Spanish"],Project_Type:"One-Time Project",Description:"This job requires Java and Javascript developers",Status:"open",Proposal_Questions:["question1?","question2?"],Entity:"JOBPOST",Organization_Name:"ABC Company",Jobpost_ID:"JOBPOST-20220608-10",Jobpost_Title:"Web Developer",Organization_ID:"ORGANIZATION-1000",Rates:"$20/hour",Experience:"< 3 Years",Created_Date:20220608,Location:"Singapore",SK:"JOBPOST-20220608-10",PK:"ORGANIZATION-1000",Skill_Set:["HTML","Javascript"]},{Languages:["English","French"],Project_Type:"Ongoing Project",Description:"This job requires DB design skills",Status:"Closed",Proposal_Questions:["Question A?","Question B?"],Entity:"JOBPOST",Organization_Name:"ABC Company",Jobpost_ID:"JOBPOST-20220608-11",Jobpost_Title:"Database Developer",Organization_ID:"ORGANIZATION-1000",Rates:"$20/hour",Experience:"< 3 Years",test:["test"],Created_Date:20220610,Location:"TBD",SK:"JOBPOST-20220608-11",PK:"ORGANIZATION-1000",Skill_Set:["DynaomDB","GraphDB"]}]};

ReactDOM.render(
  <Example res={res} />,
  document.getElementById('react')
);
.heading { font-size: 1em; color: black; }
.heading:hover { color: royalblue; cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.