I'm writing a react code that shows JSON data in a tabular form. And there is a button, on click of which, I want to total the column's data, add it to a new column(sum
), and display. Here is my code.
import { useState } from "react";
const NewTable = () => {
const [data, setData] = useState([
{ val: 2, val2: 3, val3: 1 },
{ val: 4, val2: 1, val3: 9 },
{ val: 6, val2: 1, val3: 1 }
]);
const keys = Object.keys(data[0]);
const processData = () => {
data.map((item) => {
var currRowValues = Object.values(item);
var nd = currRowValues.reduce((a, b) => {
return a b;
});
return (item["sum"] = nd);
});
setData(data);
};
return (
<div>
<table>
<thead>
<tr>
{keys.map((item, idx) => (
<th key={idx}>{item}</th>
))}
</tr>
</thead>
<tbody>
{data.map((item, idx) => (
<tr>
{keys.map((key, idx) => (
<td key={idx}>{item[key]}</td>
))}
</tr>
))}
</tbody>
</table>
<button onClick={processData}>Submit</button>
</div>
);
};
export default NewTable;
Currently, the new row is getting added when I save the code but not when I click on the submit button. Please let me know how can I fix this. Here is a working fiddle of the same.
Thanks
CodePudding user response:
I think you're mistaking the use of Array.map
. Array.map
will create a new array and apply what is return from the call back function on each element, you can read more here. With that said, the setState
in processData
will basically do nothing since your data is not change and you're setting state with what you initialize the state with. To use the new map value, you can assign that to a variable or constant and use that like below:
...
const processData = () => {
var rowWithSum = data.map((item) => {
var currRowValues = Object.entries(item);
var nd = currRowValues.reduce((a, [key, value]) => {
if(key === 'sum'){
return a
}
return a value;
}, 0);
return {...item, sum: nd};
});
setData(rowWithSum);
};
...
I've also modify so that it create a new key in the object using spread operator, which you can read more on it here, and also to not accidentally add the existing sum to the next sum by check the key using Object.entries
.
CodePudding user response:
You're not getting a re-render because React does a referential equality comparison of props/state when making a decision to re-render.
data
has the same reference as the original state data
array because of which the functional component does not re render on setData
Change setData(data)
to setData([...data])
which returns a new copy of the array.
You can have a look on how to update objects and arrays in state - https://beta.reactjs.org/apis/usestate#updating-objects-and-arrays-in-state