I am trying to update every current value based on the previous value of another property.
Actually, I need to do the task with dates, but just to keep it simple, I’ll explain my problem with simple numbers.
I have
Start, which is1.Stop, which is already definedEndDuration, which is already defined
My goal
Start=Durationof previous index +Endof previous indexEnd=Start+Stopof current value
To illustrate, I added the screenshot of the table, how it should look like.
Desired view
Current View
Code below and sandbox link
import React from "react";
import { AgGridReact } from "ag-grid-react";
import "./styles.css";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-alpine.css";
function App() {
let start = 1;
const [gridApi, setGridApi] = React.useState(null);
const [gridColumnApi, setGridColumnApi] = React.useState(null);
const onGridReady = (params) => {
setGridApi(params.api);
setGridColumnApi(params.columnApi);
};
const defaultColDef = {
flex: 1,
editable: true
};
const columnDefs = [
{
headerName: "Name",
field: "name"
},
{
headerName: "start",
field: "updatedStart"
},
{ headerName: "stop", field: "stop" },
{
headerName: "end",
field: "end"
},
{
headerName: "duration",
field: "duration",
colId: "duration"
}
];
const rowData = React.useMemo(
() => [
{
name: "John",
stop: 10,
duration: 5
},
{
name: "David",
stop: 15,
duration: 8
},
{
name: "Dan",
stop: 20,
duration: 6
}
],
[]
);
const rowDataWithStart = React.useMemo(() => {
return (
rowData &&
rowData.map((row, i) => ({
...row,
start: start
}))
);
}, [start, rowData]);
const rowDataWitEnd = React.useMemo(() => {
return (
rowDataWithStart &&
rowDataWithStart.map((row, i) => ({
...row,
end: row.start + row.stop
}))
);
}, [rowDataWithStart]);
//this function(rowDataWitUpdatedStart) should get the previous value of end and duration and get the total
const rowDataWitUpdatedStart = React.useMemo(() => {
return (
rowDataWitEnd &&
rowDataWitEnd.map((row, i) => ({
...row,
updatedStart: row.end + row.duration
}))
);
}, [rowDataWitEnd]);
return (
<div className="App">
<h1 align="center">React-App</h1>
<div className="ag-theme-alpine">
<AgGridReact
columnDefs={columnDefs}
rowData={rowDataWitUpdatedStart}
defaultColDef={defaultColDef}
domLayout={"autoHeight"}
onGridReady={onGridReady}
></AgGridReact>
</div>
</div>
);
}
export default App;
I have tried to do the task making a use of valueGetter from the library I use: AG Grid, but seems to be not the best approach. See my previous question
Any help will be appreciated
>Solution :
Instead of having a step-wise transformation of your data, you can simply do all the operations you want in one go, using Array.prototype.reduce. The way we are going to use Array.prototype.reduce here is going to be almost similar to how you use Array.prototype.map (we are pushing the objects as-is into a new array, so there is no transformation of data), but the advantage is that we have access to the current index in the third argument, which allows us to access values of the previous item.
With your logic, where you want start to be the duration + end of the previous item, we can use this logic:
curCopy.start = idx === 0 ? 1 : (acc[idx - 1].duration + acc[idx - 1].end);
…which basically says:
- If we are on the first time, just start with the seed value of
1forstart - If not, then we access the previous entry (current index minus one) of the accumulator, and access its
durationandendproperties. Sum them up and use them forstart
Use this logic in a new memoized array of objects returned:
const updatedRowData = React.useMemo(() => {
const updated = rowData.reduce((acc, cur, idx) => {
const curCopy = {...cur};
const previous = acc[idx - 1];
curCopy.start = idx === 0 ? 1 : (previous.duration + previous.end);
curCopy.end = curCopy.start + curCopy.stop;
acc.push(curCopy);
return acc;
}, []);
return updated;
}, [rowData]);
And then in your template, simply use rowData={updatedRowData}.
It should generate the results that you expected:
I have forked your sandbox to create a proof-of-concept example:


