Hi I want to be able to modify an array of objects in state using a for loop and would like to know the best way of going about this!
const [ paymentData, setPaymentData ] = useState([
{
paymentN: 'First Payment',
paymentDate: 'March 07'
},
{
paymentN: 'Second Payment',
paymentDate: 'March 24'
},
{
paymentN: 'Third Payment',
paymentDate: 'April 8th',
},
{
paymentN: 'Fourth Payment',
paymentDate: 'April 21st'
}
])
Specifically I want to modify the dates in each object in my paymentData state array. My intended final result would something like
{
paymentN: 'First Payment',
paymentDate: 'Mon Mar 14 2022 07:17:05 GMT-0400'
},
{
paymentN: 'Second Payment',
paymentDate: 'Mon Mar 28 2022 07:17:05 GMT-0400'
},
{
paymentN: 'Third Payment',
paymentDate: 'Mon Apr 11 2022 07:17:05 GMT-0400'
},
{
paymentN: 'Fourth Payment',
paymentDate: 'Mon Apr 25 2022 07:17:05 GMT-0400'
}
My function is intended to get the current date, increment it by 2 weeks and then set the new date at object[i]. My idea was to take the previous state data create a new array of objects with the modified date and set it to state again.
const createPaymentPlan = ( amount, e ) => {
e.preventDefault();
const currentDate = new Date()
var obj = []
for ( let i = 0 ; i < 4 ; i ) {
currentDate.setDate(currentDate.getDate() 14)
const updatedPaymentData = paymentData[i]
updatedPaymentData.paymentDate = currentDate
obj.push(updatedPaymentData)
}
setPaymentData(obj)
}
When I tried this my final state looks like this, however when I console.log the updatedPaymentData variable it is set to the correct incremented date in each loop.
CodePudding user response:
Each object is referring to the same date object causing all of them to have the same date after the loop. You can create a new Date in each iteration to fix this.
const paymentData = [{
paymentN: 'First Payment',
paymentDate: 'March 07'
},
{
paymentN: 'Second Payment',
paymentDate: 'March 24'
},
{
paymentN: 'Third Payment',
paymentDate: 'April 8th',
},
{
paymentN: 'Fourth Payment',
paymentDate: 'April 21st'
}
]
const currentDate = new Date()
const array = []
for (let i = 0; i < paymentData.length; i ) {
currentDate.setDate(currentDate.getDate() 14)
const updatedPaymentData = paymentData[i]
updatedPaymentData.paymentDate = new Date(currentDate);
array.push(updatedPaymentData)
}
console.log(array)
It's better to make sure that the state's values are of the same type/format across renders so you can do this conversion and use the converted array as the initial state.
// this can be defined somewhere outside the component
const formatPaymentData = (paymentData) => {
return paymentData.reduce(
((currentDate) => (formatted, curr) => {
currentDate.setDate(currentDate.getDate() 14);
formatted.push({ ...curr, paymentDate: new Date(currentDate) });
return formatted;
})(new Date()),
[]
);
};
const [paymentData, setPaymentData] = useState(
formatPaymentData([
{
paymentN: 'First Payment',
paymentDate: 'March 07',
},
{
paymentN: 'Second Payment',
paymentDate: 'March 24',
},
{
paymentN: 'Third Payment',
paymentDate: 'April 8th',
},
{
paymentN: 'Fourth Payment',
paymentDate: 'April 21st',
},
])
);
CodePudding user response:
const createPaymentPlan = ( amount, e ) => {
e.preventDefault();
let currentDate=new Date();
let finalPayment=paymentData.map((e)=>{
currentDate=new Date(new Date().setDate(currentDate.getDate() 1))
e.paymentDate=currentDate;
return e
})
setPaymentData(finalPayment);
}