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>
))
Related
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.
How to input array into 1 column table ? Audience number 2 have 2 Films B & C. I want to become 1 column. ex [Film B, Film C] in Column Film.
My Table =>
The Table Image
const AudienceListComponent = () => {
const [audience, setAudience] = useState([])
console.log("audience", audience)
const getAllAudience = () => {
AudienceService.getAllAudiences().then((response) => {
console.log('response', response)
setAudience(response.data)
})
}
useEffect(() => {
getAllAudience()
}, [])
return (
<div>
<table className="table table-bordered table-bordered">
<thead className="table-dark">
<tr>
<th>No</th>
<th>Audience Name</th>
<th>Film</th>
</tr>
</thead>
<tbody>
{
audience.map((aud, i) => (
<tr key={aud.id}>
<td>{i + 1}</td>
<td>{aud.name}</td>
{aud.film.map(films =>
<td>{films.title}</td>
)}
</tr>
))
}
</tbody>
</table>
</div>
);
};
export default AudienceListComponent;
Solved by #Hamza Khan in a comment:
You need to run the map loop inside your td element like this: <td> {aud.film.map(films => films.title )} </td>
I am creating a functional component am fetching some data from an internal API and am wondering how I can make destructure the table rows into something a little less verbose. The following is the response I am getting from this API.
{
"data": [
{
"id": "cc134653-c463-4e79-8b9e-f52dfe02498e",
"type": "bottle",
"attributes": {
"name": "Luc Belaire Rare Luxe",
"price": "$29.99",
"image": "https://cdn11.bigcommerce.com/s-
7a906/images/stencil/1000x1000/products/10929/10518/Luc-Belaire-Rare-Luxe__73902.1555086630.jpg?c=2",
"sku": "813497005010",
"size": "750ML",
"origination": "France",
"varietal": "Sparkling Wine"
}
},
}
I am setting the state of the component like this.
const [bottles, setBottles] = useState([]);
useEffect(() => {
fetch('http://localhost:3000/api/v1/bottles?', { method: "GET" })
.then(response => response.json())
.then(data => setBottles(data.data));
});
This is how I am creating a table body in my component but am wondering if there is a better way to use the bottle.attributes.name and other attributes to make it more like {name}. How can I achieve this?
<tbody>
{bottles.map(bottle =>
<tr key={bottle.id}>
<td><img src={bottle.attributes.image} alt={bottle.attributes.name} height={150} width={100}/></td>
<td>{bottle.attributes.name}</td>
<td>{bottle.attributes.sku}</td>
<td>{bottle.attributes.price}</td>
<td>{bottle.attributes.size}</td>
<td>{bottle.attributes.origination}</td>
<td>{bottle.attributes.varietal}</td>
</tr>
)}
</tbody>
It will have to be a bit repetitive regardless - if you destructure the argument, you'll have to list out each individual property in the argument list:
{bottles.map(({ id, attributes: { image, name, sku, price, size, origination, varietal }}) =>
<tr key={id}>
<td><img src={image} alt={name} height={150} width={100}/></td>
<td>{name}</td>
<td>{sku}</td>
I'd prefer to just destructure to get the attributes, and then list attributes.name, etc:
<tbody>
{bottles.map(({ id, attributes }) =>
<tr key={id}>
<td><img src={attributes.image} alt={attributes.name} height={150} width={100}/></td>
<td>{attributes.name}</td>
<td>{attributes.sku}</td>
which is better than going through bottle each time.
You could make an array of the property names and use an inner map()
const attrs =['name', 'sku', 'price', 'size', 'origination', 'varietal']
<tbody>
{bottles.map(bottle =>
<tr key={bottle.id}>
<td><img src={bottle.attributes.image} alt={bottle.attributes.name} height={150} width={100}/></td>
{attrs.map(k => <td>{bottle.attributes[k]}</td>}
</tr>
)}
</tbody>
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>
));
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>
)
}