Hi I am getting two array of objects from APi and trying to render in a table, using spread operator i am combining the two arrays and binding but the problem is in table it is rendering two times how to combine the two arrays and print as one value in table for one email Id as emailid is unique in both the arrays.
Below is the code and attached link of stackblitz:
export default function App() {
const [allData, setAllData] = useState([]);
let data = {
status: 'success',
Candidates: [
{
Recruiter: 'Pradeep',
Email: '[email protected]',
Total: 11,
Hired: 2,
interviewscheduled: 0,
clientsubmitted: 1,
Withdrawn: 0,
Onhold: 5,
inprocess: 0,
Rejected: 1,
Available: 0,
tobeupdated: 2,
},
{
Recruiter: 'Sudhir',
Email: '[email protected]',
Total: 6,
Hired: 1,
interviewscheduled: 0,
clientsubmitted: 1,
Withdrawn: 0,
Onhold: 1,
inprocess: 0,
Rejected: 0,
Available: 0,
tobeupdated: 3,
},
],
Jobopenings: [
{
Recruiter: 'Pradeep',
Email: '[email protected]',
jobopeningTotal: 4,
},
{
Recruiter: 'Sudhir',
Email: '[email protected]',
jobopeningTotal: 7,
},
{
Recruiter: 'Marry Scott',
Email: '[email protected]',
jobopeningTotal: 1,
},
],
};
useEffect(() => {
let data1 = [...data.Candidates, ...data.Jobopenings];
setAllData(data1);
}, []);
return (
<div>
<table >
<thead>
<tr>
<th scope="col">Recruiter Name</th>
<th scope="col">Job Openings</th>
<th scope="col">Hired Candidates</th>
<th scope="col">Candidates</th>
<th scope="col">Clients' Submissions</th>
<th scope="col">Interviews Scheduled</th>
</tr>
</thead>
{allData?.map((eachItem, index) => {
return (
<tbody>
<tr key={eachItem.Email}>
<td scope="row">{eachItem.Recruiter}</td>
<td>{eachItem.jobopeningTotal}</td>
<td>{eachItem.Hired}</td>
<td>{eachItem.Total}</td>
<td>{eachItem.clientsubmitted}</td>
<td>{eachItem.interviewscheduled}</td>
</tr>
</tbody>
);
})}
</table>
</div>
);
}
https://stackblitz.com/edit/react-vzlp1c?file=src/App.js,src/style.css
CodePudding user response:
You want some way to merge the 2 arrays together such that items with repeated Keys
(Email in your case) get combined and others get inserted. You can probably find a bunch of libs that already have such helper functions, or you can write a short one yourself.
This should do what you want:
useEffect(() => {
function merge(arrayOne, arrayTwo, key) {
let result = [...arrayOne];
arrayTwo.forEach((entryTwo) => {
let existing = result.find((entry) => entry[key] === entryTwo[key]);
if (existing) {
Object.assign(existing, entryTwo);
return;
}
result.push(entryTwo);
});
return result;
}
setAllData(merge(data.Candidates, data.Jobopenings, 'Email'));
}, []);
CodePudding user response:
you can use lodash for it
let result = _.unionBy(data.Candidates, data.Jobopenings, "Email")
result =result.map((item,index)=>{
return {...item, jobopeningTotal:_.find(data.Jobopenings,{Email:item.Email}).jobopeningTotal }
})
console.log("Your desired output",result);
Thank you!
CodePudding user response:
You can create a temporary object obj1
with Array.prorotype.map() and Array.prorotype.reduce() from the arrays data.Candidates
and data.Jobopenings
but keeping track of the repeated data by Email
and finally get the result array value with Object.values()
Code:
useEffect(() => {
const obj1 = [...data.Candidates, ...data.Jobopenings]
.map((o) => ({
Email: o.Email,
Recruiter: o.Recruiter,
jobopeningTotal: o.jobopeningTotal || 0,
Hired: o.Hired || 0,
Total: o.Total || 0,
clientsubmitted: o.clientsubmitted || 0,
interviewscheduled: o.interviewscheduled || 0,
}))
.reduce((a, c) => {
a[c.Email] = a[c.Email] || {
Email: c.Email,
Recruiter: c.Recruiter,
jobopeningTotal: 0,
Hired: 0,
Total: 0,
clientsubmitted: 0,
interviewscheduled: 0,
};
a[c.Email].jobopeningTotal = c.jobopeningTotal;
a[c.Email].Hired = c.Hired;
a[c.Email].clientsubmitted = c.clientsubmitted;
a[c.Email].interviewscheduled = c.interviewscheduled;
a[c.Email].Total = c.Total;
return a;
}, {});
const data1 = Object.values(obj1);
setAllData(data1);
}, []);
And here is teh Stackblitz: https://stackblitz.com/edit/react-wy9d7t?file=src/App.js