We don't know what your array of objects look like so we have to guess:
So I guess this input:
const initState = [
{ id: 1, name: "bread", quantitiy: 50 },
{ id: 2, name: "milk", quantitiy: 20 },
{ id: 3, name: "water", quantitiy: 10 }
];
And I get this output:

It's completely flexible so if we have input:
const initState = [
{ id: 1, name: "bread", quantitiy: 50, location: "cupboard" },
{ id: 2, name: "milk", quantitiy: 20, location: "fridge" },
{ id: 3, name: "water", quantitiy: 10, location: "fridge" }
];
Then we get this output:

The most important thing is to map over the object values inside the map which maps over the state array:
{state.map((item) => (
<tr key={item.id}>
{Object.values(item).map((val) => (
<td>{val}</td>
))}
</tr>
))}
full demo below and on codePen: https://codepen.io/Alexander9111/pen/zYvEbML
I used a functional component but it would be very similar with a class-based component.
NOTE: you could also create a row component and then call that component inside the map over the state array. Inside this row component, you would map of the Object keys like I did and output table data elements. It's a balance between death by component (i.e. breaking down everything into smaller and smaller components nested inside each other) and fewer components which are too complex.
function MyTable() {
const initState = [
{ id: 1, name: "bread", quantitiy: 50, location: "cupboard" },
{ id: 2, name: "milk", quantitiy: 20, location: "fridge" },
{ id: 3, name: "water", quantitiy: 10, location: "fridge" }
];
const [state, setState] = React.useState(initState);
return (
<table>
<tr key={"header"}>
{Object.keys(state[0]).map((key) => (
<th>{key}</th>
))}
</tr>
{state.map((item) => (
<tr key={item.id}>
{Object.values(item).map((val) => (
<td>{val}</td>
))}
</tr>
))}
</table>
);
}
ReactDOM.render(<MyTable />, document.getElementById("target"));
th,
td {
border: 1px solid black;
margin: 0px 0px;
padding: 5px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="target"></div>
Answer from Alex L on Stack OverflowWe don't know what your array of objects look like so we have to guess:
So I guess this input:
const initState = [
{ id: 1, name: "bread", quantitiy: 50 },
{ id: 2, name: "milk", quantitiy: 20 },
{ id: 3, name: "water", quantitiy: 10 }
];
And I get this output:

It's completely flexible so if we have input:
const initState = [
{ id: 1, name: "bread", quantitiy: 50, location: "cupboard" },
{ id: 2, name: "milk", quantitiy: 20, location: "fridge" },
{ id: 3, name: "water", quantitiy: 10, location: "fridge" }
];
Then we get this output:

The most important thing is to map over the object values inside the map which maps over the state array:
{state.map((item) => (
<tr key={item.id}>
{Object.values(item).map((val) => (
<td>{val}</td>
))}
</tr>
))}
full demo below and on codePen: https://codepen.io/Alexander9111/pen/zYvEbML
I used a functional component but it would be very similar with a class-based component.
NOTE: you could also create a row component and then call that component inside the map over the state array. Inside this row component, you would map of the Object keys like I did and output table data elements. It's a balance between death by component (i.e. breaking down everything into smaller and smaller components nested inside each other) and fewer components which are too complex.
function MyTable() {
const initState = [
{ id: 1, name: "bread", quantitiy: 50, location: "cupboard" },
{ id: 2, name: "milk", quantitiy: 20, location: "fridge" },
{ id: 3, name: "water", quantitiy: 10, location: "fridge" }
];
const [state, setState] = React.useState(initState);
return (
<table>
<tr key={"header"}>
{Object.keys(state[0]).map((key) => (
<th>{key}</th>
))}
</tr>
{state.map((item) => (
<tr key={item.id}>
{Object.values(item).map((val) => (
<td>{val}</td>
))}
</tr>
))}
</table>
);
}
ReactDOM.render(<MyTable />, document.getElementById("target"));
th,
td {
border: 1px solid black;
margin: 0px 0px;
padding: 5px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="target"></div>
item is an object from the array. So this object will have key(s) and value(s). You need to retrive those and show
For example suppose array is like
orderDetails=[{
OrderID:1,
CustomerID:'someName'
}]
Then in map you need to do
<table>
{this.state.orderDetails.map((item =>
<tr key={item.OrderID}>{item.CustomerID}</tr>
))}
</table>
how can i map over 2 Array of object in React and render to one Table
const [dataSetOne, setDataSetOne] = useState()
const [dataSettwo, setDataSetTwo] = useState()
``let URL1 = "http://api_url/users"
let URL2 = "http://api_url/users-card"
const promise1 = axios.post(URL1, inputValue , {headers: {'Content-Type': 'text/plain'}});
const promise2 = axios.post(URL2, inputValue , {headers: {'Content-Type': 'text/plain'}});
Promise.all([promise1, promise2]).then(function(values) {
setDataSetOne(values[0]);
setDataSetTwo(values[1]);
}); <TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableCell>{DataOne}</TableCell>
<TableCell>{DataOne}</TableCell>
<TableCell>{DataTwo}</TableCell>
</TableBody>
</Table>
</TableContainer>You're doing
{item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
}
that prints false like <tr>false</tr> if mobile_open is false.
try
{item.mobile_open ?
(<tr className="test-td">
<td>...</td>
</tr>) : null
}
As for the div warning consider using React 16 Fragments
using React 16.0 fragment syntax
<tbody>
{myList.map((item, i) => {
return [
<tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
<td className="toggler">
{item.mobile_open && <ArrowUp />}
{!item.mobile_open && <ArrowDown />}
</td>
<td>{item.elem_one}</td>
<td>{item.elem_two}</td>
<td>{item.elem_three}</td>
</tr>,
{item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
}
];
})}
</tbody>
But I prefer the most recent React 16.2 Fragment Syntax
import React, { Fragment } from "react";
<tbody>
{myList.map((item, i) => {
return (
<Fragment>
<tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
<td className="toggler">
{item.mobile_open && <ArrowUp />}
{!item.mobile_open && <ArrowDown />}
</td>
<td>{item.elem_one}</td>
<td>{item.elem_two}</td>
<td>{item.elem_three}</td>
</tr>
{item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
}
</Fragment>
);
})}
</tbody>
More on fragments here
In React16 you are now able to return an array of components allowing you to remove the <div />.
The code would look something like :
<tbody>
{myList.map((item, i) => {
return [
<tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
<td className="toggler">
{item.mobile_open && <ArrowUp />}
{!item.mobile_open && <ArrowDown />}
</td>
<td>{item.elem_one}</td>
<td>{item.elem_two}</td>
<td>{item.elem_three}</td>
</tr>,
//This inline conditional makes it weird but this works
...[item.mobile_open &&
<tr className="test-td">
<td>...</td>
</tr>
]
];
})}
</tbody>
I want to display movies row-by-row without changing the data model.
Here's my code:
import * as React from "react";
import { useTable } from "react-table";
const borderStyle = {
border: "1px dashed navy"
};
export default function App() {
const data = React.useMemo(
() => [
{
actor: "Johnny Depp",
movies: [
{
name: "Pirates of the Carribean 1"
},
{
name: "Pirates of the Carribean 2"
},
{
name: "Pirates of the Carribean 3"
},
{
name: "Pirates of the Carribean 4"
}
]
}
],
[]
);
const columns = React.useMemo(
() => [
{
Header: "Actor",
accessor: "actor",
},
{
Header: "Movies",
accessor: (row, index) => {
console.log({ row });
// i want to display this row-by-row instead of in 1-row without changing data model
return row.movies.map(movie => movie.name);
}
}
],
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow
} = useTable({ columns, data });
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps()} style={borderStyle}>
{column.render("Header")}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row);
if (i == 0) {
console.log({ row });
}
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell, j) => {
if (i == 0 && j < 2) {
console.log({ cell, i, j });
}
return (
<td
{...cell.getCellProps()}
style={borderStyle}
>
{cell.render("Cell")}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
);
}It currently looks like:
https://user-images.githubusercontent.com/16436270/80309485-00e48380-87f3-11ea-8040-9c08f4c2e866.PNG
Here's the direct link to it: https://codesandbox.io/s/modest-sanderson-z0keq?file=/src/App.tsx
My movie list is an array of objects so how will I display it beside actor name? So it looks like:
https://i.stack.imgur.com/xZBcJ.png
Edit: Solution can be found here
i’ve never used react-table and i could be wrong but i feel like is way more complicated than it needs to be
I might be unhelpful but I believe a more “React” way to design it would be to utilise the encapsulation philosophy. You can create the table headings component and just pass props into it. Make actor component and pass props into that. Then make a movies component that you will map props into. Also make actors component and pass actor into that. You can use a highly powerful CSS grid to arrange them into a desired table layout which would take you 2 minutes to set up if you already know grid (it’s also easy to learn if you know css flexbox). I don’t believe you need to change your data structure for this.
If you want to know how to do that then you can just use map.
Data = [ { actor, movies},...]
data.map( actor =>
Actor.name Actor.movies
)
Please change this part like below
vm.map(x => x.Virtual_Machines).map(y => (
<tr>
<td>{x.VM_Name}</td>
<td>{x.VM_Location}</td>
<td>{x.VM_Encryption}</td>
</tr>
));
Your mapping is wrong, you have four levels / nesting in your JSON including Virtual_Machines, machine type, machine attributes and VM_Publisher_Info. You have mixed Virtual_Machines with machine attributes (VM_Location, VM_Encryption) that is wrong.
A similar case is:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const data = [
{
name: "Jude",
position: "Developer",
experiences: [
{
id: 0,
job: "React UI Developer",
period: "2017-2018",
description:
"I love Creating beautiful Smart UI with React js and styled components"
},
{
id: 1,
job: "React/ Redux UI Developer",
period: "2017-2018",
description:
"I love Creating beautiful Smart UI with React js and styled components"
}
]
}
];
class App extends React.Component {
state = {
data: []
};
componentDidMount() {
console.log(data);
this.setState({ data });
}
render() {
const { data } = this.state;
const resume = data.map(dataIn => {
return (
<div key={dataIn.name}>
{dataIn.name}
<ul>
{dataIn.experiences.map(experience => (
<li key={experience.id}>{experience.job}</li>
))}
</ul>
{dataIn.position}
</div>
);
});
return <div>{<React.Fragment>{resume}</React.Fragment>}</div>;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
mapping a nested array from json in React js
One possible issue that I can see is not properly setting state in handleSubmit. You should do something like this:
handleSubmit = (e) => {
e.preventDefault();
const copyStateInvoices = [...this.state.invoices]
copyStateInvoices.push({
description: this.state.description,
unit: this.state.unit,
quantity: this.state.quantity
})
this.setState({
invoices: copyStateInvoices,
})
//console.log(this.state.invoices[].description);
};
Component's state is immutable and if you try to change the values in state it will happen but react will not respect that. Read more about these fundamentals on react main website.
Thanks
Try with following changes.
Needs change in pushing objects to an array state
To push objects or values or numbers in react you should do something like below. The recommended approach to push values to an array in React is using prevState
handleSubmit = (e) => {
e.preventDefault();
this.setState(prevState => ({
invoices: [...prevState.invoices, {
description: this.state.description,
unit: this.state.unit,
quantity: this.state.quantity
}]
}));
};
And in .map you no need to do invoice[index] to get the value because you are doing .map on array so it gives you each object in loop so you can directly access invoice.unit directly and invoice[index].unit is not needed and not correct in loop
const list = this.state.invoices.map((invoice, index) => {
return (
<tr key={index}>
<td>{invoice.description}</td>
<td>{invoice.unit}</td>
<td>{invoice.quantity}</td>
<td>{invoice.unit * invoice.quantity}</td>
</tr>
)
});
Your problem might not be an optimization problem. What you are searching for is to have only one function that return the render for keys of your object. Here is a suggestion:
- Change you
renderYear()method to this:
renderField(objectKey) {
if (this.props.total_calculation.length === 0) {
return null;
}
return this.props.total_calculation.map(function (obj, key) {
return (
<td key={key} colSpan="2">
{obj[objectKey]}
</td>
);
});
}
The argument objectKey of the renderField() method takes as argument a string that is a key of the object you want to render. Then now you can call it like this:
<tr className='year'>
<td>Year</td>
{{this.renderField('Year')}}
</tr>
You can call the renderField() method on other key of your object like 'rent_increase'
You should also check the Open/closed principle of the SOLID principles because your problem has similar solution to it.
You can try the below code,
const renderField = () =>
this.props.total_calculation.length > 0 ? (
this.props.total_calculation.map(function (obj, key) {
return (
<td key={key} colSpan="2">
{obj['Year']}
</td>
);
})) : null;
I think this is what you are looking for:
const res = {
data: [
{
_id: "603a651e22",
name: "name 1",
state: "F",
createdAt: "2021-02-25T17:13:42.218Z",
participants: [
{
name: "something",
email: "[email protected]",
},
{
name: "something 2",
email: "[email protected]",
},
],
},
{
_id: "sdfhfh312312",
name: "name",
state: "F",
createdAt: "2021-02-26T18:43:49.240Z",
participants: [
{
name: "something",
email: "[email protected]",
},
{
name: "something 2",
email: "[email protected]",
},
],
},
],
};
console.log(res.data);
return (
<div>
<table>
<thead>
<tr>
<th>#</th>
<th>name</th>
<th>state</th>
<th>created</th>
<th>participants</th>
</tr>
</thead>
<tbody>
{res.data?.map((item, index) => {
return (
<tr key={index}>
<th scope="row">{item._id}</th>
<td>{item.name}</td>
<td>{item.state}</td>
<td>{item.createdAt || ""}</td>
<td>
<ul>
{item.participants.map((p, i) => {
return (
<li key={i}>
{p.name} || {p.email}
</li>
);
})}
</ul>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
Let me know if it works!
This mostly depends on how you want to display your participants. A simple example would be:
<td>
<ul>
{item.participants.map((participant) => (
<li>{participant.name} ({participant.email})</li>
))}
</ul>
</td>
Which creates an unordered list for participants and renders each participant into its own list item.