I had a context's state that have an array with some objects inside of him. the objects are something like
state[
{
name: name,
value: 200,
unit: 2
},
{
name: othername,
value: 50,
unit: 1
}]
I need to multiply the value with the units and then sum with the other objects.
I tried to use
useEffect(()=>{
state.items.map((each) => {
return setSubtotal( previousValue => previousValue + each.unit * Number(each.price));
},[state])
it works for sum, but when i remove some object of the state, i dont know what i have to do to subtract the value. Someone can help me?
I hope this code will help you, I put a reducer on it
const subTotal = state.items.reduce((previousValue , each) => each.unit * Number(each.price) + previousValue , 0);
useEffect(()=>{
setSubtotal( subTotal );
},[subTotal])
Related
I have a data structure like this :
var records = [
{
firstName: "Akira",
id: "0543236543",
},
{
firstName: "Harry",
id: "0994372684",
},
{
firstName: "Sherlock",
id: "0487345643",
},
{
firstName: "Kristian",
id: "04873452342",
},
];
I want to create a function that would add the date property (adjusted for hours) to each of object in the array depending on the length of the array.
Here's my code so far
function updateObject(obj) {
let timeNow = new Date();
let addHours = (h) => timeNow.setHours(timeNow.getHours() + h);
const ids = obj.map((record) => record.id);
const lastNames = obj.map((record) => record.id);
const time = obj.map(
(record, index) => (record["time"] = new Date(addHours(index)))
);
return obj;
}
This returns:
[
{
firstName: 'Akira',
id: '0543236543',
time: 2021-05-18T12:25:59.366Z
},
{
firstName: 'Harry',
id: '0994372684',
time: 2021-05-18T13:25:59.366Z
},
{
firstName: 'Sherlock',
id: '0487345643',
time: 2021-05-18T15:25:59.366Z
},
{
firstName: 'Kristian',
id: '04873452342',
time: 2021-05-18T18:25:59.366Z
}
]
First issue: I want to update the time by adding 0,1,2,3 hours to the current time.
Currently it:
adds 0 to time and sets is a current time
adds 1 to updated time and set it a as a current time and so on.
Second:
I want to modify the function so it takes an add additional argument, "time increment" that if set to x will update the time property for first x records for 0 hours and the next x records for 1 hour.
Hope that makes sense :)
First issue can be solved by changing addHours to be a pure function that does not mutate timeNow:
const timeNow = Date.now();
const addHours = (h) => new Date(timeNow + h * 60 * 60 * 1000);
Second issue can be solved by looking at the index in the map:
const time = obj.map(
(record, index) => (record["time"] = new Date(addHours(index > increment ? 1 : 0))));
And in general, I would advise against mutating objects/arrays. Pure functions are usually easier to reason about and offer fewer surprises.
I would write the updateObject function so it does not mutate the original, but returns a new array with new objects.
Thanks! What if the increment parameter defines how many first x records should have the time property increased by 1h
For example my contacts array length is 4.
function updateObject(records, 1) {
\\code here
}
The first object would have the time property increased by 0h.
The second object would have the time property increased by 1h.
The third object would have the time property increased by 2h.
The fourth object would have the time property increased by 3h.
function updateObject(records, 3) {
\\code here
}
The first 3 objects would have the time property increased by 0h.
The fourth object would have the time property increased by 1h.
Do I need to slice the array into sub arrays first?
I have an array of objects as my initial state like
const [product,setProduct]=useState([
{
id:1,
product_title:"Item 1",
quantity:2,
price:100.00
},
{
id:2,
product_title:"Item 2",
quantity:3,
price:300.00
},
])
Here I am also adding more items and at the same time, I Want to calculate the total amount based on quantity*price of each item from the objects. Right now I am proceeding with map() function like this code below and I am getting the exact result
const countTotal=(items)=>
{
var total=0;
product.map(item=>total+=item.quantity*item.price)
setTotal(total)
}
Now My question is if it is a good process or there is an alternative way that is better and standard than this process.
As a general rule, if you have array and want to single value based on all values, you need Array.proptotype.reduce()
const products = [
{
id:1,
product_title:"Item 1",
quantity:2,
price:100.00
},
{
id:2,
product_title:"Item 2",
quantity:3,
price:300.00
},
];
const countTotal = (items) => items.reduce((acc, curr) => acc + curr.quantity * curr.price, 0);
console.log(countTotal(products))
You are using .map method incorrectly, you should use reduce method instead, like this
const total = product.reduce((prev, cur) => {
return prev + cur.quantity * cur.price;
}, 0);
I am having difficulty calculating the total votes from the array of choices . I have a json like below
{
id:1,
pollName: 'aaaaa',
pollChoices:[
id: 2,
choice : 'dddd',
votes: [
{
}
]
]
}
I am trying to count the total number votes casted from the jon above within my memoized selectors
My code is like below
const pollChoices: Array<PollChoice> = poll.get("PollChoices").toJS();
const pollStatistic = pollChoices
.reduce((prev: any, curr: any) => {
console.log("The pollStatistic is ", prev);
return { curr, totalVotesCasted: (prev.Votes ?
(prev.Votes.length + curr.Votes.length) :
0 + curr.Votes.length )}
}, {});
console.log("The pollStatistic is ", pollStatistic);
The console within pollStatistic seems to show my totalVotesCasted, however, when i print pollStatistic, its always undefined, i want to be able to get the pollStatistic.totalCount in my state. Pls any help is appreciated.
This is not how reduce works.
You pass the reduce function a reducer callback of this signature: function reducer(accumulator, currentValue, currentIndex) { ... }
The callback should return a the value of the accumulator it wants to be passed to the next iteration.
In your case when you access prev.Votes you should be accessing prev.totalVotesCasted which is the value you set on the accumulator.
In Redux, what's the best practice to update all items in an array with items from another array only with the fields that are common to the 2 arrays.
So for example :
billArrayInStore = [{id, amount, dueDate, summary}, ...]
newBillArray = [{id, amount, dueDate}, ...]
Update each bill (amount, dueDate) but keep the 'summary' field untouched.
Thank you :)
You can use Array.prototype.map
newBillArray = billArrayInStore.map(bill => ({
...bill,
amount: 0, // new amount
dueDate: '', // new dueDate
}))
For each bill object in billArrayInStore, you want to see if there is a corresponding bill object in newBillArray by comparing IDs. If you find a matching bill object, you then merge the two bills together into a new object. These new bill objects are stored in a new array to avoid mutating the original.
Since this solution involves transforming existing bill objects and storing them in a new array, it's a perfect use case for Array.prototype.map.
const updatedBills = billArrayInStore.map(bill => {
// For each existing bill, check to see if there is a corresponding
// new bill by comparing bill IDs.
const newBill = newBillArray.find(newBill => newBill.id === bill.id);
// If there is a new bill, merge the bills together using spread syntax.
if (newBill) {
// Order matters here, you want to spread the new bill last so it
// can override any properties in the current bill. If the current
// bill has properties that don't exist in the new bill, they won't
// be changed.
return { ...bill, ...newBill };
}
// If there isn't a corresponding new bill, the current bill should be
// returned unmodified.
return bill;
});
Here's a snippet with a working example.
const billArrayInStore = [
{ id: 1, amount: 1000, summary: 'Rent' },
{ id: 2, amount: 50, summary: 'Internet' },
{ id: 3, amount: 110, summary: 'Electric' }
];
const newBillArray = [
{ id: 2, amount: 40 },
{ id: 3, amount: 125 }
];
const updatedBills = billArrayInStore.map(bill => {
const newBill = newBillArray.find(newBill => newBill.id === bill.id);
if (newBill) {
return { ...bill, ...newBill };
}
return bill;
});
console.log(updatedBills);
I am trying to change the points of selected object that in the exp below.
$scope.players = [{
name: 'Kobe',
points: 10,
asists: 0,
rebounds: 0
}, {
name: 'Jordan',
points: 20,
asists: 0,
rebounds: 0
}, {
name: 'Grant',
points: 30,
asists: 0,
rebounds: 0
},
];
and I assign an object selected with its name.
if($scope.playerName == $scope.players[i].name){
$scope.selectedPlayerPoints = $scope.players[i].points;
$scope.selectedPlayerAsists = $scope.players[i].asists;
$scope.selectedPlayerRebounds = $scope.players[i].rebounds;
}
but I can't update them:
$scope.selectedPlayerPoints.push(playerPoints);
To make it more clear please check: http://plnkr.co/edit/B8Nydni586Se79fDpjnq?p=preview
How it works:
1-click on a player
2-click on points = each time 2 points will be added.
3-as you add more point, it will change the object dynamically..(but that is the problem..)
Thnx in advance!
I'm not exactly sure what you want to achieve, but my guess is you have trouble with saving player points.
I've updated your plunkr. Basically instead of passing primitive values:
$scope.selectPlayer = function(name, points, asists, rebounds) { ... }
you should pass object reference:
$scope.selectPlayer = function(player) { ... }