React streamich / react-use upsert example - reactjs

I would like to update a list in a react component using react-use upsert function.
const [aList, { upsert: upsertAList }] = useList({id: 0, name: 'Foo'});
The documentation say:
upsert: (predicate: (a: T, b: T) => boolean, newItem: T) => void; — Like updateFirst but in case of predicate miss - pushes item to the list.
But it doesn't help me.
Can anyone give me an example how to use it?
let elem = {id:1, name: 'Bar'}
I would like to upload the element in the list with the new one.
upsertAList(____) // <- what hould I write here instead of '____'?
Thanks in advice.

const [aList, { upsert: upsertAList }] = useList({id: 0, name: 'Foo'});
let repElem = {id: 0, name: 'bar'};
upsert( (a,b) => { if (a.id === b.id) return true }, newElem );

Related

How to duplicate object in react

Even replicating the object succeeded. However, the id value is duplicated the same. Therefore, if you click the delete button, the deletion will be done together.But I want to get a different ID. How can I fix it here?
const handleduplicate = id => {
const dupDataGroup = [...Groupdata].filter(item => item.id === id);
const newGroup = [dupDataGroup[0], ...Groupdata];
setGroupData(newGroup);
};
The result when I didn't do anything =>
0: {id: 0, title: 'blur', subtitle: 'Img'}
1: {id: 1, title: 'blurs', subtitle: 'Ima'}
2: {id: 2, title: 'Free ', subtitle: 'Ima'}
handleduplicate click result=>
0: {**id: 0**, title: 'blur', subtitle: 'Img'}
1: {**id: 0,** title: 'blur', subtitle: 'Img'}
2: {id: 1, title: 'blurs', subtitle: 'Ima'}
3: {id: 2, title: 'Free ', subtitle: 'Ima'}
I hope that only the ID value will change when duplicated.
React does not automatically update the key index in JSON objects. Also, in this scenario, you're fetching the value and inserting it into the newGroup.
If you really want to update the keys, I'd suggest creating a for loop to update the values of id.
const handleduplicate = id => {
const dupDataGroup = [...Groupdata].filter(item => item.id === id);
const newGroup = [dupDataGroup[0], ...Groupdata];
for (var i = 0; i < newGroup.length; i++)
newGroup[i].id = i;
setGroupData(newGroup);
};
You can duplicate an object by using the spread operator.
const obj = {name: 'ritik', surname: 'banger'};
const objCopy = {...obj};
or use of Object.assign will work for you.
let objcopy = Object.assign({}, obj);
You must note that here we are referencing the original object 'obj' and thus any changes in 'objcopy' will reflect in 'obj', this is known as shallow copy.
If you want to deep copy the object and you wish to have different reference for both then,
Using JQuery library:
import jQ from "jquery";
let objcopy = jQ.extend(true, obj, {});
Using lodash library:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
[...Groupdata] creates a new list with the (non-duplicated) items in Groupdata. This is important if you'd want to add the item twice to the list, as changing one with change the same object as you already noticed. You will also have to duplicate the item itself.
Note that duplicating the list itself isn't necessary if you're just going to filter on it.
What I also think is happening, given the additional information in the comments, is that setGroupData is used multiple times. If you use Groupdata, followed by setGroupData, then Groupdata is not updated accordingly. So just make sure you use that function once.
const handleduplicate = (groupData, id, newId) => {
const dupDataGroup = groupData.filter(item => item.id === id); // no copying here.
const rest = groupData.filter(item => item.id !== id);
const newGroup = [
{ // the item is duplicated (note: no deep copy)
...dupDataGroup[0],
id: newId // updated with the new identifier
},
...rest
];
return newGroup;
};
const duplicated = handleduplicate(Groupdata, 123, 456);
setGroupData(duplicated);

Flatten object type with array property in typescript react for output to react-data-grid

Apologies in advance if this has already been answered, but I am struggling to find an answer to it...
I have an array which contains a 2 d array property.
What I want returned is a type which contains has the inner array as a flat object.
So for example my array could be
{
name: "Widget",
event: "Xmas",
pilot: "Dave",
session: "drinking",
frameType: "flight",
stint: 2016,
plane: "737",
**data: {
"114": "137.623",
"115": "51.090",
}**
}
What I would like is my output to be
{
name: "Widget",
event: "Xmas",
pilot: "Dave",
session: "drinking",
frameType: "flight",
stint: 2016,
plane: "737",
"114": "137.623",
"115": "51.090",
,
}
Now here is my code to generate the array.
The Type:
type TableItem =
{
name: string,
event: string,
session: string,
frameType: string,
stint: number,
chassis: string,
driver: string,
data: (string | number)[][]
};
const getTableItem = (index: number) =>
{
const d = data[index];
//Transformentry just makes the id 3 digits
const dataItems = Object.assign({}, ...Object.entries(d.data).map(transformEntry));
const tableItem: TableItem = {
name: d.name,
event: d.event,
piolt: d.pilot,
session: d.session,
frameType: d.frameType,
stint: d.stint,
plane: d.plane,
data: dataItems
};
return tableItem;
};
const rows = (data.map((d, index) => { return getTableItem(index); }));
Now what I want is the rows variable(const) to contain the flattened array. I have tried flat/flatmap and reduce but can't get them to work.
If anyone can point me in the right direction with this it would be massively appreciated. Basically the rows const will then be passed to the react-data-grid component.
Thanks in advance
Steve
The data property is not an array, it is another object which may be why things like flatMap did not work for you.
If you're happy to retain the data property but also flatten the properties therein into the top level object you could just flatten it with the spread operator ...:
const input = {
name: "Widget",
event: "Xmas",
pilot: "Dave",
session: "drinking",
frameType: "flight",
stint: 2016,
plane: "737",
data: {
"114": "137.623",
"115": "51.090",
}
};
const result = {...input,...input.data};
console.log(result);
If you must get rid of the data property you could just add delete result.data; to the above.

typescript how to find inside an array that is already in an array?

I want to find a value inside an array that is already inside an array.
To give an example of my array:
[
{
ConcessionId: 1,
ConcessionName: "Coyotes",
KnownAs: [
{
TeamId: 1,
Name: "Arizona Coyotes",
},
{
TeamId: 2,
Name: "Phoenix Coyotes",
}
]
},
{
ConcessionId: 2,
ConcessionName: "Devils",
KnownAs: [
{
TeamId: 3,
Name: "Colorado Rockies",
},
{
TeamId: 4,
Name: "New-Jersey Devils",
}
]
}
]
What I want is when Icall my function it returns me the team name.
For example, I the parameter value is 3, I want Colorado Rockies as a name:
public getInfo(_TeamID) {
const concession: ConcessionInfo[] = this.concessionList$.filter(function (x) {
x.KnownAs.filter( (y)=> {
y.TeamId= +_TeamID;
return y.Name;
})
})
}
I try so many different way with filter. But never get something good. Never works.
I can make a double .foreach , for each array. but I think a better method exist than making a double loop.
Thanks
Instead of using the filter method (which is in fact working similar as a for loop), you could do forEach on both arrays. For your current data structure, there is no other way around it.
getInfo = (_TeamID) => {
let teamName = '';
this.concessionList$.forEach(entry => {
entry.KnownAs.forEach(team => {
if(team.TeamId === _TeamID){
teamName = team.Name;
return; // break the loop.
}
})
});
return teamName;
}
Here is a working example
https://stackblitz.com/edit/double-for-lopp
EDIT
If you have a look at the polyfill implementation of filter from Mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter which is in equivalent to the native implementation of filter, you can see that it is looping through the whole array, the same way as a forEach loop. The difference is that the filter method will return a new array based on the boolean condition inside the callback function, while a forEach loop does not return anything.
Assuming myArray is contains the data you provided.
The following code will work if you're using Typescript 3.7 and above.
public getInfo(teamId: number): string | undefined {
const team = this.concessionList$
.map(concession => concession.KnownAs)
.reduce((a, b) => a.concat(b), [])
.find(team => team.TeamId === teamId)
return team ? team.Name : undefined
}
Usage:
this.getInfo(3) // Colorado Rockies
Ok how this work?
You have to understand what is find. For example:
const result = [{name: 'foo', age: 1}, {name: 'bar', age: 2}]
.find(people => people.name === 'foo')
console.log(result) // {name: 'foo', age: 1}

Angular Filter and Merge Array of Objects [duplicate]

This question already has answers here:
Most efficient method to groupby on an array of objects
(58 answers)
Closed 3 years ago.
I have:
arrayBefore
arrayBefore = [{name:'n1', items: [i1]}, {name:'n2', items: [i2]}, {name:'n1', items: [i3]}]
I want to create a function:
myFunction
myFunction(arrayBefore)
So it will produce:
arrayAfter
arrayAfter = [{name:'n1', items: [i1, i3]}, {name:'n2', items: [i2]}]
I have tried to implement myFunction using map() and filter(), but I can't get it working correctly. I would show some code I tried if I had the idea I was getting close, unfortunatly this is not the case. Any help would be greatly appreciated!
reduce method is what you are looking for:
const result = arr.reduce((a, {name, items})=>{
a[name] = a[name] || { name, items:[] };
a[name].items.push(...items)
return a;
}, {});
An example:
let arr = [
{ name: 'n1', items: ['i1'] },
{ name: 'n2', items: ['i2'] },
{ name: 'n1', items: ['i3'] }
];
const result = arr.reduce((a, {name, items})=>{
a[name] = a[name] || { name, items:[] };
a[name].items.push(...items)
return a;
}, {});
console.log(Object.values(result))
This looks like the groupBy operation. It's not doable by only map and filter. You need a reduce. See an example here

React native identify a boolean within an object

I am trying to make an app(IOS and Android) for ads and I want to be able to go into the objects of my ads and identify a boolean and if it is true do one thing and something else otherwise.
Here are the objects of an ad:
I want to go into the object and if the "ReceiveHelp" is true i want the code to execute say blue as backgroundcoulor otherwise red. The problem is I don't know how to go into the object and identify the boolean props only.
export const publicAdFetch = () => {
return (dispatch) => {
firebase.database().ref('/users').once('value').then((snapshot) => {
const usersData = snapshot.val();
let sortedAdds = Object.keys(usersData).reduce((prev, userId) => {
let ads = usersData[userId].ads;
ads = Object.keys(ads).map(key => {
return { ...ads[key], id: key };
});
return prev.concat(ads);
}, [])
.sort((a, b) => (b.time - a.time));
this is the code I currently have to put everything into an array and then sort by time. But I have no idea how to just see if the boolean is true or false
You can check for a boolean with typeof
const yourObjArray = [
{desc: "fdf", price: "rrr", receiveHelp: true},
{desc: "ccc", price: "254", receiveHelp: 351},
{desc: "aaa", price: "gdg", receiveHelp: false},
{desc: "aaa", price: "gdg", receiveHelp: "charlie"},
{desc: "feee", price: "jth", receiveHelp: true},
];
yourObjArray.forEach(obj => console.log("The type is: ", typeof obj.receiveHelp));
Once you know if the receiveHelp is a boolean you can check for true or false easily with if():
const receiveHelp = true;
if (typeof receiveHelp === 'boolean') {
if (receiveHelp) { // This equals to if (receiveHelp === true)
console.log("this is true: ", receiveHelp);
} else { // else false
console.log("this is false: ", receiveHelp);
}
}
Thanks #Rodius
You're help gave me some inspiration!
I solved it but doing:
let iftrue = '#666';
if (this.props.callbackFromParent.receiveHelp) {
iftrue = '#ff0';
and then in my styles for the ad i had "iftrue", didn't realize it was so simple that ".receiveHelp" was enough to go into the object to check on the values.

Resources