Iterating over object and displaying as table - React.js - javascript

I have an object:
{
cities: {
MCR: "Manchester",
LDN: "London",
NYC: "New York"
}
}
and I want to iterate over these and display them in a table format which will show the city code and the long name next to it. Something like:
<tbody>
<tr>
<th>City Code</th>
<th>City Name</th>
</tr>
<tr>
{Object.entries(cities).map(([key, value]) => {
<>
<td>{key}</td>
<td>{value}</td>
</>
}
)}
</tr>
</tbody>
However this doesn't display anything and also shows an error when hovering over value:
Type 'unknown' is not assignable to type 'ReactNode'.ts(2322)
I'm quite new to React and wondering how best to display this information?
Thanks

let say you have an object as:
const obj = {
cities: {
MCR: "Manchester",
LDN: "London",
NYC: "New York"
}
};
It would be better to loop over cities and create a new tr so that It looks like a table
CODESANDBOX LINK
You want to map over the cities then you should return it from map as:
<tbody>
<tr>
<th>City Code</th>
<th>City Name</th>
</tr>
{ Object.entries( obj.cities ).map( ( [key, value] ) => {
return ( // PROBLEM SHOULD RETURN
<tr>
<td>{ key }</td>
<td>{ value }</td>
</tr>
);
}
) }
</tbody>

You need to return the result in each iteration. Also, each iteration would return a tr with a key prop:
{
Object.entries(obj.cities).map(([key, value]) => (
<tr key={key}>
<td>{key}</td>
<td>{value}</td>
</tr>
))
}
Note: since city is a key in an object, you'll need to access it as above

You are just missing the return in your map's callback function. Always remember to include a return in your arrow functions when using it like this: () => {}. It is easy to miss because ()=>() would return whatever you write in the second () but in the former example this is not true.

Related

React Table Increment Button

I'm very new to React, and I'm trying to make a table using react that displays information about a car. Currently, I'm trying to implement two buttons on each row that would increment/decrement a certain field of the table.
This is the code for the table:
render() {
return (
<table>
<tr>
<th>Manufacturer</th>
<th>Model</th>
<th>Year</th>
<th>Stock</th>
<th>Price</th>
<th>Options</th>
<th></th>
</tr>
{
this.state.cars.map(car =>
<tr key={car.model}>
<td>{car.manufacturer}</td>
<td>{car.model}</td>
<td>{car.year}</td>
<td>{car.stock}</td>
<td>${car.price}</td>
<td><button type="button" onClick={this.increaseStock.bind(this)}>Increment</button></td>
<td><button type="button" onClick={this.decreaseStock.bind(this)}>Decrement</button></td>
</tr>
))
}
</table>
);
};
This so far is just fine for displaying the data and buttons, however, I'm not actually sure how to implement the buttons' functions
All the implementations for increaseStock and decreaseStock so far have done nothing on click, although I think they're being called. I'm trying to get it to either add to the stock value or subtract from it(not going below 0).
I've tried things using states, but I'm not really sure how those work.
Here's an example of how your component could be implemented. I used the functional component and a state hook because those are what I'm familiar with.
import React, { useState } from "react";
export default function CarTable() {
const [cars, setCars] = useState([
{ id: 1, name: "Car 1", stock: 5 },
{ id: 2, name: "Car 2", stock: 10 }
]);
const increase = (index) => {
const oldCar = cars[index];
// copying the car with the updated stock
const newCar = { ...oldCar, stock: oldCar.stock + 1 };
//copying the car array
const newCars = [...cars];
//replacing the old car with a new one in a new array
newCars[index] = newCar;
//updating state
setCars(newCars);
};
const decrease = (index) => {
// same as above except decreasing the stock now
const oldCar = cars[index];
const newCar = { ...oldCar, stock: oldCar.stock - 1 };
const newCars = [...cars];
newCars[index] = newCar;
setCars(newCars);
};
return (
<table>
<thead>
<tr>
<th>name</th>
<th>stock</th>
<th></th>
</tr>
</thead>
<tbody>
{cars.map((car, i) => (
<tr key={car.id}>
<td>{car.name}</td>
<td>{car.stock}</td>
<td>
<button onClick={() => increase(i)}>increase</button>
<button onClick={() => decrease(i)}>decrease</button>
</td>
</tr>
))}
</tbody>
</table>
);
}
In short what you need to do is create a new car object with the updated stock property. Then create a new cars array with the new car object just mentioned and then set the state to this new cars array.
Here's also a CodeSandbox link where you can try it out:
https://codesandbox.io/s/charming-dijkstra-8brqz1?file=/src/CarTable.js
Hope that helps.

How can ı add my values to table in react

I am trying to make form project. When person submmit to personal info to form. I want add this info to Table. But I get this error when I am adding info to table.
Uncaught Error: Objects are not valid as a React child (found: object with keys {inputValue}). If you meant to render a collection of children, use an array instead.
I know this is related to const newToTable part. But I don't know how to make it right. Please help me, ıf you know how can ı solve this problem.
This is my contact.js
const buttonOnClick = () => {
if (inputValue === "" || emailValue === "" || phoneNumberValue === "") {
setShowModal(false);
} else {
setShowModal(true);
// setInputValue("");
//setEmailValue("");
//setPhoneValue("");
// sa
}
const newToTable = [...addFormData, { fullName:{inputValue},email:{emailValue}, phoneNumber:{phoneNumberValue},country:{countryValue} }];
setAddFormData(newToTable);
console.log(`Form submitted, ${showModal}`);
}
This is my AddTable.js
<div className="app-container">
<form>
<Table>
<thead>
<tr>
<th>Full Name</th>
<th>Email </th>
<th>Phone Number</th>
<th>Country</th>
</tr>
</thead>
<tbody>
{addFormData.map((addForm) => (
<tr>
<td>{addForm.fullName}</td>
<td>{addForm.email}</td>
<td>{addForm.phoneNumber}</td>
<td>{addForm.counry}</td>
</tr>
))}
</tbody>
</Table>
</form>
</div>
You've accidently wrapped your form values in objects here:
const newToTable = [...addFormData, { fullName:{inputValue},email:{emailValue}, phoneNumber:{phoneNumberValue},country:{countryValue} }];
For example fullName:{inputValue} will evalute to fullName: { inputValue: 'the value' }
Instead you need:
const newToTable = [
...addFormData,
{
fullName: inputValue,
email: emailValue,
phoneNumber: phoneNumberValue,
country: countryValue,
},
];
This is what the error means by Objects are not valid as a React child - when it tries to render your table, the values being passed are objects such as { inputValue: 'the value' } (this is the (found: object with keys {inputValue}) part of the error - an object with inputValue as a key).

Creating dynamic table, Object.keys not allowing to return rows of table react

I am creating a dynamic table. If I writing a function like this:-
function renderTable(Category) {
return (
<table>
<tr>
<th>Status</th>
<th>Name</th>
<th>Product</th>
</tr>
{data.data.changer.map(changer=> {
const valuePresent = changer.attack.find(
x => x.unique === category.name
);
if (valuePresent) {
return (
<tr>
<td>{changer.rule_status}</td>
<td>{changer.vendor_rule_name}</td>
<td>{changer.firewall_vendor}</td>
</tr>
);
}
})}
</table>
);
}
It returns the perfect table of how I need it.
But If I try to make the key as dynamic as well like:-
function renderTable(Category) {
return (
<table>
<tr>
<th>Status</th>
<th>Name</th>
<th>Product</th>
</tr>
{Object.keys(data.data).forEach((key, index) => {
if (Category=== key) {
{
data.data[key].map(changer=> {
const valuePresent = changer.attack.find(
x => x.unique === category.name
);
if (valuePresent) {
return (
<tr>
<td>{changer.rule_status}</td>
<td>{changer.vendor_rule_name}</td>
<td>{changer.firewall_vendor}</td>
</tr>
);
}
});
}
}
})}
</table>
);
}
it does not return rows, or and
Any Idea why I want to make key's as well dynamic
Array.prototype.forEach() doesn't return anything, so the JSX in your inner map are never returned. If your goal is to only render the data with the property coverageCategory, I would instead get that property and then do the the map like you have initially, e.g.:
function renderTable(coverageCategory) {
const data = coverageData.data[coverageCategory];
return (
<table>
<tr>
<th>Rule Status</th>
<th>Rule Name</th>
<th>Product name</th>
</tr>
{data.firewall.map(firewall => {
const valuePresent = firewall.mitre_attack.find(
x => x.technique === categorySelected.name
);
if (valuePresent) {
return (
<tr>
<td>{firewall.rule_status}</td>
<td>{firewall.vendor_rule_name}</td>
<td>{firewall.firewall_vendor}</td>
</tr>
);
}
})}
</table>
);
}
An improvement would also be to filter:
data.firewall
.filter((firewall) =>
firewall.mitre_attack.some((x) => x.technique === categorySelected.name)
)
.map((firewall) => (
<tr>
<td>{firewall.rule_status}</td>
<td>{firewall.vendor_rule_name}</td>
<td>{firewall.firewall_vendor}</td>
</tr>
));

How to render my multidimensional array of objects in react

I am trying to render my array of objects inside my table but it shows "Cannot read property 'monthlytarget' of undefined", I am using axios to fetch the result and render inside the table
Axios :
http.get(apiReportsEndpoint+"?empid="+this.props.match.params.id)
.then(response =>{
this.setState({
report:response.data.data.monthlytarget
})
});
Response I receive from API
"data":{
"monthlytarget":[
{
"quarter":1,
"period_start":"2019-04-01",
"monthlytarget":{
"04":{
"targetpm":"213120",
"invoice_values":[
],
"revenuepm":0,
"targetpercentage":0,
"joinees":0
},
"05":{
"targetpm":"213120",
"invoice_values":[
],
"revenuepm":0,
"targetpercentage":0,
"joinees":0
}
}
},
{ quarter":2 ...},
{ quarter":3 ...},
]
}
I want to render values inside "monthlytarget" as rows inside table
<thead>
<tr>
<th>MONTH</th>
<th>TARGET PER MONTH</th>
<th>REVENUE PER MONTH</th>
</tr>
</thead>
<tbody>
{
this.state.report.map((revenuereport) =>{
{Object.keys.map.monthlytarget(premise,index) => (
<tr>
<td>{index}</td>
<td>{premise.targetpm}</td>
<td>{premise.revenuepm}</td>
</tr>
))}
})
}
</tbody>
To create one table out of all the data you could do the following:
this.state.report
.map(({ monthlytarget }) => Object.entries(monthlytarget))
.flat()
.map(([key,value], index) => (
<tr key={index}>
<td>{index}</td>
<td>{value.targetpm}</td>
<td>{value.revenuepm}</td>
</tr>
));
what do you mean by calling Object.keys.map.monthlytarget? if you are trying to loop the array and get JSX, do this:
this.state.report.map((revenuereport) =>
Object.keys(revenuereport.monthlytarget).map((premise, index) => (
<tr>
<td>{index}</td>
<td>{revenuereport.monthlytarget[premise].targetpm}</td>
<td>{revenuereport.monthlytarget[premise].revenuepm}</td>
</tr>
))
);
Do pay attention to indents and brackets, code snippet in the question seems not gonna work at all.
It should be...
this.state.report.map(({ monthlytarget }, i) =>
Object.values(monthlytarget).map({ targetpm, revenuepm }, i) =>
<tr>
<td>{i}</td>
<td>{targetpm}</td>
<td>{revenuepm}</td>
</tr>
))

Cannot render child object in React JS table

I am trying to render an object held in state. The contents of this.state is:
"statement": {
"creator": "8ff243b2-f21e-43f3-9090-4aa679fbeb1a",
"id": "bf4c965e-bd59-48c8-b31a-8f67529e5fde",
"impactors": [
"978388e8-2987-4c89-82b6-4da619d82935",
"1d75e2a7-bf2a-4f55-ba68-373752b24f98"
],
"score": {
"impactors": 2,
"net": 3,
"percentage": 0.75,
"total_votes": 4
},
"statement": "The Earth is round."
}
In my React JS app, I am able to render some of the child object (statement) but not all. Here is my code:
renderStatement() {
return (
<tbody>
<tr>
<td>Statement: </td>
<td>{this.state.statement.score}</td>
</tr>
</tbody>
)
}
As expected, the above code returns an error: Error: Objects are not valid as a React child (found: object with keys {impactors, net, percentage, total_votes}). If you meant to render a collection of children, use an array instead.
What I actually want is percentage, which is a node underneath score. When I try to drill down and have it just render percentage, like this:
renderStatement() {
return (
<tbody>
<tr>
<td>Statement: </td>
<td>{this.state.statement.score.percentage}</td>
</tr>
</tbody>
)
}
I get the following error: TypeError: Cannot read property 'percentage' of undefined.
Any of the other objects ('creator', 'id', 'impactors', 'statement') work just fine.
This is how I fixed it:
renderStatement() {
const score = this.state.statement.score || {}
return (
<tbody>
<tr>
<td>Statement: </td>
<td>{score.percentage}</td>
</tr>
</tbody>
)
}
you can do the following:
renderStatement() {
const text = (typeof this.state.statement.score !== "undifined") ?
this.state.statement.score.percentage : ''
return (
<tbody>
<tr>
<td>Statement: </td>
<td>{text}</td>
</tr>
</tbody>
)
}

Categories