how to add object to empty list - reactjs

I am trying to add object to list using setInterval to auto add the object every 1second but the output returns null as first index
Here my code below, I don't know where am getting it wrong
;
const [list, setList] = useState([])
const winners = [
{
name:'john',
price: '200'
},
{
name:'Micheal',
price: '230'
}
]
useEffect(() => {
const interval = setInterval(() => {
setSeconds(second => (second >= winners?.length ? 0 : second + 1));
}, 3000);
if(list?.length >=0){
const newList = list.concat(winners?.[`${seconds}`])
setList(newList)
}
if(winners.length === list?.length){
clearInterval(interval);
}
return () => clearInterval(interval)
}, [seconds]);
This is the output am getting // output
list = [
null,
{
name:'john',
price: '200'
},
null,
{
name:'Micheal',
price: '230'
}
]
**but I want this
list = [
{
name:'john',
price: '200'
},
{
name:'Micheal',
price: '230'
}
]

As far as I can read from your code, you could remove all null values from the Array, by applying a filter method on it.
Try this:
setList(newList.filter(item != null));

Related

find a specifik obejct with arrays and print it out, react

I want to use find when clicking a button, I want to find an obejct (working in react)
let numbers = [
{ id: 0, namn: one, img: "../number/one" },
{ id: 1, namn: two, img: "../number/two" },
{ id: 2, namn: three, img: "../number/three" },
];
const [selected, setSelected] = useState({
id: 0,
name: "one",
img: "../number/one",
});
const count = useRef(0);
function next() {
if (count.current === 2) {
count.current = 0;
let found = numbers.find((number) => number.id === count.current);
} else {
count.current = count.current + 1;
let foundtwo = numbers.find((number) => number.id === count.current);
}
return (
<>
<img>{selected.img}</img>
namn: {selected.name}
</>
);
}
I can find it but I want to put it in a useState.
or somehow get it to show. how can I get found, and found two out in the return
the awswer was to put a
if( found === undefined){
console.log("error")
}else{
setSelected(found)
}

Replacing value in nested state with react functional components

I am trying to use update state in a react function component but it is not working. I tried following a tutorial on pluralsite and apply it to my own project. Ideally this code should be finding the product based on the ID number and replacing the total with a new value.
Unfortunately I am getting an error saying that 'productData.find' is not a function and I'm not sure where the code being used for that is. Are there any suggestions on how to solve this issue?
This is what the data looks like. In this example I am saving the first element of the array.
export let data = [
{
name: "Name",
description:
"",
products: [
{
id: 1,
name: "Name 1",
material: 1.05,
time: 25,
total: 0,
},
{
id: 2,
name: "Name 2",
material: 3,
time: 252,
total: 0,
},
],
},
...
];
function CompareCard({}) {
const index = 0;
const [productData, setProductData] = useState(data[index]);
function setTotalUpdate(id) {
const productPrevious = productData.find(function (rec) {
return rec.id === id;
});
const productUpdated = {
...productPrevious,
total: 1,
};
const productNew = productData.map(function (rec) {
return rec.id === id ? productUpdated : rec;
});
setProductData(productNew);
}
setTotalUpdate(1)
}
It's because productData is not an array so .find would not work. You want iterate over the products property in your data, so do productData.products.find(...)
When you do
const [productData, setProductData] = useState(data[index])
you don't pass an Array on your state but an Object (the first element of your data so an Object) and Object don't have find method.
Try
const [productData, setProductData] = useState([data[index]])
with [] on our useState to put your Object on array
///////////////////////////////// Edit /////////////
Ok, I try your code, and I propose you this.
import React, { useState } from "react";
const data = [
{
name: "Name",
description: "",
products: [
{
id: 1,
name: "Name 1",
material: 1.05,
time: 25,
total: 0,
},
{
id: 2,
name: "Name 2",
material: 3,
time: 252,
total: 0,
},
],
},
];
const CompareCard = () => {
// setState with the subArray products from data[0], I use '...' (spread operator) inside a Array or an Object to make a shalow copy
const [productsData, setProductsData] = useState([...data[0].products]);
const setTotalUpdate = (id) => {
// find the product to change inside products collection, that's ok
const productPrevious = productsData.find((rec) => {
return rec.id === id;
});
// create a new product to change one property's value, you can do something like 'productPrevious.total = 1', same same
const productUpdated = {
...productPrevious,
total: 1,
};
// create a new products collection to update state
const productNew = productsData.map((rec) => {
return rec.id === id ? productUpdated : rec;
});
setProductsData([...productNew]);
};
const setTotalUpdateSecond = (id) => {
// create a newState
const newState = productsData.map((product) => {
// condition if id === productId and do something
if (id === product.id) {
product.total = 1;
}
// both case, I return the product (change or not)
return product;
});
setProductsData([...newState]);
};
return (
<>
<button onClick={() => setTotalUpdate(1)}>Test old method on product 1</button>
<button onClick={() => setTotalUpdateSecond(2)}>Test second method on product 2</button>
{productsData.map((product) => {
return (
<>
<p>Product Id : {product.id} / Product Total : {product.total}</p>
</>
);
})}
</>
);
};
export default CompareCard;
Can you copy / past this, try and say me if it's what you want, if yes, I explain you where the confusion was. If not, explain me, what's the problem here and I modificate.

How can I delete an item inside a nested array with Hooks?

I am trying to remove a single item from state inside a nested array, but i am really struggling to understand how.
My data looks as follows, and I'm trying to remove one of the 'variants' objects on click.
const MYDATA = {
id: '0001',
title: 'A good title',
items: [
{
itemid: 0,
title: 'Cheddar',
variants: [
{ id: '062518', grams: 200, price: 3.00},
{ id: '071928', grams: 400, price: 5.50},
]
},
{
itemid: 1,
title: 'Edam',
variants: [
{ id: '183038', grams: 220, price: 2.50},
{ id: '194846', grams: 460, price: 4.99},
]
},
{
itemid: 2,
title: 'Red Leicester',
variants: [
{ id: '293834', grams: 420, price: 4.25},
{ id: '293837', grams: 660, price: 5.99},
]
}
]
}
Against each variant is a button which calls a remove function, which (should) remove the deleted item and update the state. However, this is not happening and I'm not sure what I am doing wrong.
const [myCheeses, setMyCheeses] = useState(MYDATA);
const removeMyCheese = (variantID, itemindx) => {
console.log(variantID);
setMyCheeses((prev) => {
const items = myCheeses.items[itemindx].variants.filter(
(variant) => variant.id !== variantID
);
console.log(items, itemindx);
return {
...myCheeses.items[itemindx].variants,
items
};
});
};
An example of the issue I'm facing can be seen here
https://codesandbox.io/s/funny-dan-c84cr?file=/src/App.js
Any help would be truly appreciated.
The issue is that, setMyCheeses function not returning the previous state including your change(removal)
Try one of these functions;
1st way
const removeMyCheese = (variantID, itemindx) => {
setMyCheeses((prev) => {
const items = myCheeses.items[itemindx].variants.filter(
(variant) => variant.id !== variantID
);
const newState = prev;
newState.items[itemindx].variants = items;
return {...newState};
});
};
https://codesandbox.io/s/bold-worker-b12x1?file=/src/App.js
2nd way
const removeMyCheese = (variantID, itemindx) => {
setMyCheeses((prev) => {
const items = myCheeses.items.map((item, index) => {
if (itemindx === index) {
return {
...item,
variants: item.variants.filter(
(variant) => variant.id !== variantID
)
};
} else {
return item;
}
});
return { ...prev, items: items };
});
};
https://codesandbox.io/s/sharp-forest-qhhwd
try this function, it's work for me :
const removeMyCheese = (variantID, itemindx) => {
//console.log(variantID);
const newMyCheeses = myCheeses;
const newItems = newMyCheeses.items.map((item) => {
return {
...item,
variants: item.variants.filter((variant) => variant.id !== variantID)
};
});
setMyCheeses({ ...newMyCheeses, items: newItems });
};
https://codesandbox.io/s/jolly-greider-fck6p?file=/src/App.js
Or, you can do somthing like this if you don't like to use the map function :
const removeMyCheese = (variantID, itemindx) => {
//console.log(variantID);
const newMyCheeses = myCheeses;
const newVariants = newMyCheeses.items[itemindx].variants.filter(
(variant) => variant.id !== variantID
);
newMyCheeses.items[itemindx].variants = newVariants;
setMyCheeses({ ...newMyCheeses });
};

Update state that depends on other calculated state in React-Hooks

I want to update a state (data) that depends on other calculated state (server)
setServer(prevTweets =>
[...json, ...prevTweets].filter(
(e, i, arr) => i === arr.findIndex(t => t.tweetId === e.tweetId)
)
)
The data above will be used to set the state below (data) :
let totalPositive = 0;
let totalNegative = 0;
let totalNeutral = 0;
server.forEach(tweet => {
if(tweet.sentiment >0) totalPositive++;
if(tweet.sentiment < 0) totalNegative++;
if(tweet.sentiment ===0) totalNeutral++;
})
setData([
{ name: 'Positive', value: totalPositive },
{ name: 'Negative', value: totalNegative },
{ name: 'Neutral', value: totalNeutral },
])
Since it's asynchronous, the setData operation is always late. I know that I can use useEffect but apparently it will make an infinite loop and it's not right to use it in this case.
If you set the new data before you set the server you'd skip one render:
//still defaults to server so if you do't pass anything it;s still the same
const setNewData = (newServer = server) => {
const [
totalPositive,
totalNegative,
totalNeutral,
] = newServer.reduce(
([pos, neg, neu], { sentiment }) =>
sentiment > 0
? [pos + 1, neg, neu]
: sentiment < 0
? [pos, neg + 1, neu]
: [pos, neg, neu + 1],
[0, 0, 0]
);
setData([
{ name: 'Positive', value: totalPositive },
{ name: 'Negative', value: totalNegative },
{ name: 'Neutral', value: totalNeutral },
]);
};
setServer(prevTweets => {
const newServer = uniqueByTweetId([
...json,
...prevTweets,
]);
setNewData(newServer);
return newServer;
});
Unrelated to the question but could be important is that the way you get unique values could be improved. You could get unique values in one pass without having to call find index many times:
const uniqueBy = getter => arr => {
const items = new Map();
return arr.filter(item => {
const key = getter(item);
const ret = items.get(key);
items.set(key,true);
return !ret;
});
};
const data = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 1 },
{ id: 7 },
{ id: 1 },
{ id: 7 },
{ id: 8 },
{ id: 1 },
];
const uniqueById = uniqueBy(i => i.id);
console.log(uniqueById(data));

Find through array in array field

How can I find something through some arrays that also contain an array?
To be more precisely:
And I want to return from the coaches array, the id(within the coaches) that matches the username. What I've tried:
if (!(args['coach'].value === '') && (args['coach'].value !== null)) {
coachId = this.items.find(x => x.username === args.coach.value).id;
}
Basically this.items is what I've console.log before. Now it gives me undefined.
Has someone a fix for this? Thank you very much.
[
{
"id":584,
"name":"Name",
"coaches":[
{
"id":8587,
"username":"test"
},
{
"id":8589,
"username":"test1"
}
]
},
{
"id":587,
"name":"O1",
"coaches":[
]
}
]
And let s say I want to return the id 8587 when searching for the name test.
Combine map and find:
const array = [
[{a1: 1},
{a2: 2}
],
[{a1: 1},
{a2: 2},
{a3: 3}]
];
const element = array.map(innerArray => {
const found = innerArray.find(el => el.a1 === 1);
if (found) return found.a1;
return null;
}).find(el => el !== null);
console.log(element) // 1
For finding multiple matches do as follows:
const data = [{
"id": 584,
"name": "Name",
"coaches": [{
"id": 8587,
"username": "test"
},
{
"id": 8589,
"username": "test1"
}
]
},
{
"id": 587,
"name": "O1",
"coaches": [
]
}
];
const usernameToSearch = 'test1';
const foundCoachIds = data
.reduce((acc, curr) => {
// Destructure the coaches property first
const {
coaches,
...rest
} = curr;
// Check if any username matches the coach
const foundMatches = coaches.filter(x => x.username === usernameToSearch);
// If there is any found match push into accumulator
if (foundMatches.length) {
for (const foundMatch of foundMatches) {
if (acc.indexOf(foundMatch.id) === -1) {
acc.push(foundMatch.id);
}
}
}
return acc;
}, []);
console.log(foundCoachIds);
let y = this.items.filter(o => o.coaches.some(e => e.username === 'test'))[0]
.coaches.filter(e=>e.username === 'test')[0].id;
console.log(y);
const data = [
{
"id":584,
"name":"Name",
"coaches":[
{
"id":8587,
"username":"test"
},
{
"id":8589,
"username":"test1"
}
]
},
{
"id":587,
"name":"O1",
"coaches":[
]
}
];
For outer id
data.map(it => {return !!it.coaches.find(it2 => it2.username == "test") ? it.id : null}).filter(it=>!!it)
evaluates to [584]
For inner
(coaches) id:
data.map(it => it.coaches.find(it2 => it2.username == "test")).filter(it => !!it).map(it=> it.id)
returns [8587]
Just need to take the first item from these to get your answer.

Resources