Home > Blockchain >  ReactJS Array not returning all objects in Loop
ReactJS Array not returning all objects in Loop

Time:10-28

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 ?

CodePudding user response:

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>

CodePudding user response:

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>

  • Related