React merge two states in third state - javascript

I have three state, two of them have data from different api and the third state need to merge those two states based on IDs. So, the third state should have every data that state1 have and state2 don't have, and every data that state2 have and state1 don't have.
Api1:
data: {
0: {
id: 1234
company: 'String',
name: 'Test'
}
1: {
id: 2345
company: 'String1',
name: 'Test 1'
}
2: {
id: 3456
company: 'String2',
name: 'Test 2'
}
3: {
id: 4567
company: 'String3',
name: 'Test 3'
}
}
Api2:
data: {
0: {
id: 1234
company: 'String',
name: 'Test'
lastName: 'Second'
}
1: {
id: 2345
company: 'String1',
name: 'Test 1'
lastName: 'Second 2'
}
2: {
id: 3456
company: 'String2',
name: 'Test 2'
lastName: 'Second 1'
}
3: {
id: 4567
company: 'String3',
name: 'Test 3'
lastName: 'Second 3'
}
}
New Array should be (lastName = name + lastName :
data: {
0: {
id: 1234
company: 'String',
name: 'Test'
lastName: 'Second Test'
}
1: {
id: 2345
company: 'String1',
name: 'Test 1'
lastName: 'Second 2 Test 1'
}
2: {
id: 3456
company: 'String2',
name: 'Test 2'
lastName: 'Second 1 Test 2'
}
3: {
id: 4567
company: 'String3',
name: 'Test 3'
lastName: 'Second 3 Test 3'
}
Fetched Data:
const [state1, setState1] = useState([]);
const [state2, setState2] = useState([]);
const [mergeStates, setMergeStates] = useState([]);
useEffects(() => {
fetch("api1")
.then(data =>{
state1(data);
})
fetch("api2")
.then(data =>{
state2(data);
})
}, []);
useEffects(() => {
// Here I want to merge the responses based on IDs
const lastName = companies.map((response) => ({
name: response.name,
lastName: `${response.name} - ${response.lastName}`
}));
setMergeState(lastName);
}, [state1, state2]);
So, the api2 has lastName that api1 doesn't have. So, the mergedStates need to include that.

based on your quetion to merge the two state, you need to iterate over a state either 1 or 2, while merging them.
useEffects(() => {
const keys = Object.keys(state1);
mergedData = keys.map(key => {
// key will be 0,1,2 as with your quetion
return {
...state1[key],
...state2[key],
fullName: state1[key].name + state2[key].lastName
};
});
}, [state1, state2]);

Related

How can I access a specific object in my array using JavaScript?

I have created a dynamic array of objects which is created through inquirer.
But I cannot figure out how to access a specific object in the array
EDIT: this is how the console has logged my array
So for example, how can I access the 2nd Engineer (Mark)?
Keep in mind the array will change depending on the user input
team = [
Manager {
name: 'Nicole',
id: '1',
email: 'nicole#gmail.com',
officeNumber: '5'
},
Engineer {
name: 'Zoe',
id: '2',
email: 'zoe#gmail.com',
github: 'zozo'
},
Engineer {
name: 'Mark',
id: '3',
email: 'mark#gmail.com',
github: 'emman'
},
Engineer {
name: 'Joe',
id: '4',
email: 'joe#gmail.com',
github: 'joey'
}
Intern {
name: 'Seb',
id: '5',
email: 'seb#gmail.com',
school: 'UWA'
}
]
Use find method. If there is no such Mark then find return null.
If you want find Engineer Mark
const result = data.find(x => {
return x instanceof Engineer && x.name === 'Mark'
})
[Update]
If you want find the second Engineer
const result = data.filter(x => {
return x instanceof Engineer
})[1]
As Sepehr jozef mentioned the strucure is not that handy. If we take his structure you can find it via the .find Method.
var team = [
{
name: 'Nicole',
id: '1',
email: 'nicole#gmail.com',
officeNumber: '5',
},
{
name: 'Zoe',
id: '2',
email: 'zoe#gmail.com',
github: 'zozo'
},
{
name: 'Mark',
id: '3',
email: 'mark#gmail.com',
github: 'emman'
},
{
name: 'Joe',
id: '4',
email: 'joe#gmail.com',
github: 'joey'
},
{
name: 'Seb',
id: '5',
email: 'seb#gmail.com',
school: 'UWA'
}
]
const mark = team.find(function(teamMember){
return teamMember.name === "Mark";
})
The variable "mark" contains now the object of the engineer "Mark".
first of all, your structure is wrong.
it should be:
var team = [
{
name: 'Nicole',
id: '1',
email: 'nicole#gmail.com',
officeNumber: '5',
},
{
name: 'Zoe',
id: '2',
email: 'zoe#gmail.com',
github: 'zozo'
},
{
name: 'Mark',
id: '3',
email: 'mark#gmail.com',
github: 'emman'
},
{
name: 'Joe',
id: '4',
email: 'joe#gmail.com',
github: 'joey'
},
{
name: 'Seb',
id: '5',
email: 'seb#gmail.com',
school: 'UWA'
}
]
and to get mark(2) you should use:
team[3].name

How to match data and combine two arrays of objects? [duplicate]

This question already has answers here:
How can I perform an inner join with two object arrays in JavaScript?
(7 answers)
Closed 1 year ago.
My database gives me the following data:
var responses = [
{ comment: 'Yes', uid: '5hg' },
{ comment: 'Maybe', uid: 'f1' },
{ comment: 'No', uid: 'b1k2' },
{ comment: 'Yes', uid: '6t2' },
{ comment: 'Yes', uid: 'hd1' },
];
var users = [
{ name: 'Trevor Hansen', group: 'Group 1', uid: 'f1' },
{ name: 'Britta Holt', group: 'Group 2', uid: '5hg' },
{ name: 'Jane Smith ', group: 'Group 2', uid: '6t2' },
{ name: 'Sandra Adams', group: 'Group 1', uid: 'c92c' },
{ name: 'Ali Connors', group: 'Group 1', uid: 'b2' },
{ name: 'John Smith', group: 'Group 2', uid: '9l2' },
{ name: 'Sandra Williams', group: 'Group 2', uid: 'hd1' },
{ name: 'Tucker Smith', group: 'Group 1', uid: 'b1k2' },
];
Because I store all of my user data only in users[] for different purposes I need to add some information to responses[] about the user (like their name and group). The uid is unique and can be used to match the data to a user.
Obviously there are less responses than users in responses[]. This should not affect my function and is an expected behavior.
This is the desired output:
var output = [
{ comment: 'Yes', uid: '5hg', name: 'Britta Holt', group: 'Group 2' },
{ comment: 'Maybe', uid: 'f1', name: 'Trevor Hansen', group: 'Group 1' },
{ comment: 'No', uid: 'b1k2', name: 'Tucker Smith', group: 'Group 1' },
{ comment: 'Yes', uid: '6t2', name: 'Jane Smith ', group: 'Group 2' },
{ comment: 'Yes', uid: 'hd1', name: 'Sandra Williams', group: 'Group 2' },
];
How can this be done? Any help is appreciated!
you can try for example:
const output = responses.map(response => {
const user = users.find(u => u.uid === response.uid);
return {...response, ...user}
})
or single liner:
const output = responses.map(response => ({...response, ...users.find(u => u.uid === response.uid)}));

display object array as html with out brackets

Hello i have created an object array in JavaScript. And i'm trying to display the object array as html without the brackets. But i have only started to learn javascript today and i have no idea how i can do it.
let servers = [
{ id: '12345', name: 'server #1', players: 1 },
{ id: '123456', name: 'server #2', players: 2 },
{ id: '1234567', name: 'server #3', players: 3 },
{ id: '1234568', name: 'server #4', players: 4 },
{ id: '1234569', name: 'server #5', players: 5 }
];
document.getElementById("online").innerHTML = JSON.stringify(servers);
<div id="online"></div>
How i'm trying to display it:
id: 12345, name: server #1, players: 1
id: 123456, name: server #2, players: 2
id: 1234567, name: server #3, players: 3
id: 1234568, name: server #4', players: 4
id: 1234569, name: server #5, players: 5
If someone could point me in the right direction i would really appreciate it
How about this approach? 😊
This way you can easily control how the data will be displayed.
let servers = [
{ id: '12345', name: 'server #1', players: 1 },
{ id: '123456', name: 'server #2', players: 2 },
{ id: '1234567', name: 'server #3', players: 3 },
{ id: '1234568', name: 'server #4', players: 4 },
{ id: '1234569', name: 'server #5', players: 5 }
];
var string = "";
servers.map((x) => {
string += `id: ${x.id}, name: ${x.name}, players: ${x.players} <br />`
})
document.getElementById("online").innerHTML = string;
<pre id="online"></pre>
This is easy to use and display,
you can also use map() but you don't need it here. Check difference.
https://stackoverflow.com/a/34426481/10915534
let servers = [
{ id: '12345', name: 'server #1', players: 1 },
{ id: '123456', name: 'server #2', players: 2 },
{ id: '1234567', name: 'server #3', players: 3 },
{ id: '1234568', name: 'server #4', players: 4 },
{ id: '1234569', name: 'server #5', players: 5 }
];
var rows = "";
servers.forEach(function(element,index){
rows += "id: "+element.id + ", name: "+ element.name +", Players: "+element.players+"<br>";
})
document.getElementById("online").innerHTML = rows;
<div id="online"></div>
let servers = [{
id: '12345',
name: 'server #1',
players: 1
},
{
id: '123456',
name: 'server #2',
players: 2
},
{
id: '1234567',
name: 'server #3',
players: 3
},
{
id: '1234568',
name: 'server #4',
players: 4
},
{
id: '1234569',
name: 'server #5',
players: 5
}
];
var getArrData = "";
for (i = 0; i < servers.length; i++) {
getArrData += "id:" + servers[i].id + "name:" + servers[i].name + "players:" + servers[i].players + "<br>";
}
document.getElementById("online").innerHTML = getArrData;
<div id="online"></div>
This is for as many properties in your json.
let servers = [
{ id: '12345', name: 'server #1', players: 1 },
{ id: '123456', name: 'server #2', players: 2 },
{ id: '1234567', name: 'server #3', players: 3 },
{ id: '1234568', name: 'server #4', players: 4 },
{ id: '1234569', name: 'server #5', players: 5 }
];
var output = '';
for(var i = 0; i< servers.length; i++) {;
for(var prop in servers[i]){
output += prop + ': ' + servers[i][prop] + ', ';
}
output += '<br>';
}
document.getElementById("online").innerHTML = output;
<div id="online"></div>
As an alternative to looping through the returned array, if you want to keep your approach using JSON.stringify(), you can do something like this:
const servers = [
{ id: '12345', name: 'server #1', players: 1 },
{ id: '123456', name: 'server #2', players: 2 },
{ id: '1234567', name: 'server #3', players: 3 },
{ id: '1234568', name: 'server #4', players: 4 },
{ id: '1234569', name: 'server #5', players: 5 }
];
function formatJsonString(str) {
const reNewLineInsertPoints = /},/g;
const reDeletions = /{|}|\[|\]|"/g;
const reSpaceInsertPoints = /(:|,)/g;
return str.trim()
.replace(reNewLineInsertPoints, '<br />')
.replace(reDeletions, '')
.replace(reSpaceInsertPoints, '$1 ');
}
document.getElementById("online").innerHTML = formatJsonString(JSON.stringify(servers));
<div id="online"></div>
I created a separate function for readability and re-usability but it is not strictly necessary; you could simply do:
document.getElementById("online").innerHTML = JSON.stringify(servers)
.trim()
.replace(/},/g, '<br />')
.replace(/{|}|\[|\]|"/g, '')
.replace(/(:|,)/g, '$1 ')

React Cannot read property 'lastName' of undefined

I'm trying to merge data from two API in the new API but I'm getting error Uncaught TypeError: Cannot read property 'lastName' of undefined. This is happening because is not finding lastName when it missing in API2. In this case, I want to initialize it as empty string if not able to find that in the merged API.
API 1 look:
data: {
0: {
id: 1234
company: 'String',
name: 'Test'
}
1: {
id: 2345
company: 'String1',
name: 'Test 1'
}
2: {
id: 3456
company: 'String2',
name: 'Test 2'
}
3: {
id: 4567
company: 'String3',
name: 'Test 3'
}
}
API2 look:
data: {
0: {
id: 1234
company: 'String',
name: 'Test'
lastName: 'Second'
}
1: {
id: 2345
company: 'String1',
name: 'Test 1'
}
2: {
id: 3456
company: 'String2',
name: 'Test 2'
lastName: 'Second 1'
}
3: {
id: 4567
company: 'String3',
name: 'Test 3'
lastName: 'Second 3'
}
}
Merged API look:
data: {
0: {
id: 1234
company: 'String',
name: 'Test'
lastName: 'Second Test' //lastName from API 2 + name from API 1
}
1: {
id: 2345
company: 'String1',
name: 'Test 1'
lastName: '' //lastName from API 2 + name from API 1
}
2: {
id: 3456
company: 'String2',
name: 'Test 2'
lastName: 'Second 1 Test 2' //lastName from API 2 + name from API 1
}
3: {
id: 4567
company: 'String3',
name: 'Test 3'
lastName: 'Second 3 Test 3' //lastName from API 2 + name from API 1
}
Fetched data:
const [api1, setApi1] = useState([]);
const [api2, setApi2] = useState([]);
const [mergeApi, setMergeAPi] = useState([]);
useEffect(() => {
fetch('api1')
.then((response) => {
setApi1(response);
});
});
useEffect(() => {
fetch('api2')
.then((response) => {
setApi2(response);
});
});
useEffect(() => {
const data = api1.map(getData => {
const d = api2.find((object) => {
// return object.name === api1.name;
return object.name === getData.name;
});
return {
...api1,
// name: `${d.name} - ${d.lastName}`
name: d ? `${d.name} - ${d.lastName}` : ""; // solution there
}
});
});
You can use inline || operator:
${d.lastName || ""}
Also you have to change the object here:
return object.name === getData.name; //<----change here.
Try to do this. There could be a case when in your real data could be some name taht not exist in api2.
const data = api1.map(getData => {
const d = api2.find((object) => {
return object.name === getData.name; // <---- NOTE THIS
});
if (!d) { // <---- NOTE THIS
return getData
}
return {
...getData, // <---- NOTE THIS
name: `${d.name} - ${d.lastName}`
}
});
idk if you really have id in objects, but I would compare by id, not by name.
return object.id === getData.id;
useEffect(() => {
const data = api1.map(getData => {
const d = api2.find((object) => {
// return object.name === api1.name;
return object.name === getData.name; //replaced but doesn't work
});
return {
...api1,
name: `${d.name} - ${d.lastName}`
}
});
});
Array.find return undefined if there is no matched item on array. so d could be undefind and therefore code throws error there is no 'lastname' property on d.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
useEffect(() => {
const data = api1.map(getData => {
...
if (d) {
return {
...getData,
name: `${d.name} - ${d.lastName}`
}
} else {
// some code to handle if d is undefined
}
});
});
Try something like this.
1) api1 and api2 data look like object, have Object.values to get array of values.
2) Change to find function. Checking obj2.name === obj1.name
3) check for d value before using.
const api1 = {
0: {
id: 1234,
company: "String",
name: "Test"
},
1: {
id: 2345,
company: "String1",
name: "Test 1"
},
2: {
id: 3456,
company: "String2",
name: "Test 2"
},
3: {
id: 4567,
company: "String3",
name: "Test 3"
}
};
const api2 = {
0: {
id: 1234,
company: "String",
name: "Test",
lastName: "Second"
},
1: {
id: 2345,
company: "String1",
name: "Test 1"
},
2: {
id: 3456,
company: "String2",
name: "Test 2",
lastName: "Second 1"
},
3: {
id: 4567,
company: "String3",
name: "Test 3",
lastName: "Second 3"
}
};
const data = Object.values(api1).map(obj1 => {
const d = Object.values(api2).find(obj2 => obj2.name === obj1.name);
return {
...obj1,
name: d ? `${d.name} - ${d.lastName}` : obj1
};
});
console.log(data);
I have found solution for that:
useEffect(() => {
const data = api1.map(getData => {
const d = api2.find((object) => {
// return object.name === api1.name;
return object.name === getData.name;
});
return {
...api1,
// name: `${d.name} - ${d.lastName}`
name: d ? `${d.name} - ${d.lastName}` : ""; // solution there
}
});
});

React Get second object if id is equals with another object id

I'm trying to get second object inside data if this id is equals with the id of another object.
With the code below, I'm able to get only ID and not the whole
data: {
0: {
id: 1234,
name: 'Name 1'
},
2: {
id: 4321,
name: 'Name 2'
},
3: {
id: 876,
name: 'Name 3'
}
}
instanceID: 4321
constructor(props) {
super(props);
this.state = {
defaultInstance: 0
}
}
fetch('api)
.then(response => {
console.log('Data fetched', response);
this.setState({
defaultInstance: [response.data.indexOf(response.data.find((instance) => instance.id === response.instanceID))]
});
});
So, what I want to achieve is to add to the defaultInstance that object
2: {
id: 4321,
name: 'Name 2'
},
Try this :
defaultInstance: response.data.filter(d=> d.id == response.instanceID)
This will help you.
let data = {
0: {
id: 1234,
name: 'Name 1'
},
2: {
id: 4321,
name: 'Name 2'
},
3: {
id: 876,
name: 'Name 3'
}
};
let instanceID = 4321;
let result = Object.values(data).filter(chunk => chunk.id === instanceID);
console.log(result);

Categories