Quick question more on how should I approach this below to be dry. I have data which comes from the backend and on front i use react I have a component which is basically a table. Two api calls witch return different objects. I want to reuse one component rather than creating two separate tables as below. I pass an object of data to a table component, just need to know according to the object which keys to select.
<table>
<tbody>
<tr>
<td>{name}</td>
<td>{first_test.week_day}</td>
<td>{first.four.three}</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td>{name}</td>
<td>{test.time}</td>
<td>{another.one.two}</td>
</tr>
</tbody>
</table>
two separate api requests example:
{
first: {four: {three: "different"}},
first_test: {week_day: 'Saturday'},
name: "first test"
}
{
another: {one: {two: "nice"}},
test: {time: 10:00},
name: "test"
}
so what would be a best way to approach this being dry without creating multiple components ? maybe some json schema?
It might be duplicate if someone drops the another related question would appreciate.
You conform whatever input to match your generic table component like so
function GenericTable({first, second, third}) {
return (
<table>
<tbody>
<tr>
<td>{first}</td>
<td>{second}</td>
<td>{third}</td>
</tr>
</tbody>
</table>
)
}
and call it like
<GenericTable first={name} second={first_test.week_day} third={first.four.three} />
or
<GenericTable first={name} second={test.time} third={another.one.two} />
update 1 based on comment
function GenericTable({ columns }) {
columnstb = columns.map((column, index) => (<td key={index}>{column}</td>);
return (
<table>
<tbody>
<tr>
{columnstb}
</tr>
</tbody>
</table>
)
}
and call it like
<GenericTable columns={[name, first_test.week_day, first.four.three]} />
Related
i have array of objects and iterated through the object using the array function (map)
since we have the same key on all the objects not sure how to assign AA to 123, BB to 345 and CC to 555?
AA is a hardcoded value for
Also the order of the object may change like first it may be {atr1:CC,atr2:555} then the following
Need some help to overcome this problem.
/*
{atr1: "AA", atr2: 123},
{atr1: "BB", atr2: 345},
{atr1: "CC", atr2: 555}
*/
const eList = ecom[0].esat.ttl
return (
{eList .map((list) => (
<table class="greyGridTable">
<tbody>
<tr>
<td>AA</td>
<td>{iterated value 123}</td>
</tr>
<tr>
<td>BB</td>
<td>{iterated value 345}</td>
</tr>
<tr>
<td>CC</td>
<td>{iterated value 555}</td>
</tr>
</tbody>
</table>
))}
)
Right now, you return for each object in eList an entire table, i.e. three tables.
You only need to return the content of the <tr> for the "list" parameter via .map():
return (
<table class="greyGridTable">
<tbody>
{eList.map((list) => (
<tr>
<td>{list.atr1}</td>
<td>{list.atr2}</td>
</tr>
))}
</tbody>
</table>
)
I have a database of arrays that I want to unpack and insert into a table.
For example I'll have an array called a=[1,2,3,4] and b=['a','b','c','d'] each with and equal length.
And I will have a table with just the headers
a
b
My generated array would be
[[1,'a'],[2,'b'],[3,'c'],[4,'d']] created with the zip function from the underscore package.
My goal is to iterate over this array and generate the following
a
b
1
'a'
2
'b'
3
'c'
4
'd'
At the moment, I have a
function returnIt(){
let _ = require('underscore')
//returns [[1,'a'],[2,'b'],[3,'c'],[4,'d']] so x[0] = 1 and x[1] = 'a'
for (var x of _.zip([1,2,3,4],['a','b','c','d'])){
return (
<>
<td>
{x[0]}
</td>
<td>
{x[1]}
</td>
</>
)
}
return(
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
{returnIt()}
</tr>
</tbody>
</table>
)
But this doesn't work. I get
As you can see I only get one row, the code does not produce more than one row! Sorry about the headers, I tried changing my program as much as I could to suit your eyes.
Anyways, how come this is my result and what can I change?
In returnIt, your for loop returns in the code block so it will only run once and return the first pair of array elements you've transformed to html elements. Try returning a mapping of the zipped elements to markup fragments. Then you’ll see them all.
Here's a complete example:
import _ from "underscore";
export default function App() {
return(
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
{returnIt()}
</tbody>
</table>)
}
function returnIt(){
//returns [[1,'a'],[2,'b'],[3,'c'],[4,'d']] so x[0] = 1 and x[1] = 'a'
let zipped = _.zip([1,2,3,4],['a','b','c','d'])
return zipped.map(pair => {
return (
<tr>
<td>
{pair[0]}
</td>
<td>
{pair[1]}
</td>
</tr>
)
})
}
Assuming this is using React
return (
<>
<td>
{x[0]}
</td>
<td>
{x[1]}
</td>
</>
)
<td> should be direct descendant of <tr>
The problem is you're returning from the loop body. So it'll only ever get to the first element.
for (anything) {
return ...
}
will always return immediately without continuing the loop, no matter what is between the parentheses.
You need to have the loop build up the HTML and return all the rows at once, or else maybe use something like a generator function and add a loop to the place that calls the function.
Assuming you're using some framework that lets you just return unquoted HTML like that, the problem with the table part of your return value is probably that you can't have a <div> between a <tr> and one of its enclosed <td>s.
I'm currently creating a table through React where the labels are certain object keys and the table entries are the object values. The set of data I'm using is an array of objects where I use map to get each individual object. Here's how I'm doing it.
{
data.map(graph =>
<div key={graph.ID} className="tables">
<table>
<tr>
<th>{Object.keys(graph)[0]}</th>
<th>{Object.keys(graph)[1]}</th>
<th>{Object.keys(graph)[2]}</th>
<th>{Object.keys(graph)[3]}</th>
<th>{Object.keys(graph)[4]}</th>
<th>{Object.keys(graph)[5]}</th>
<th>{Object.keys(graph)[6]}</th>
<th>{Object.keys(graph)[7]}</th>
<th>{Object.keys(graph)[8]}</th>
<th>{Object.keys(graph)[9]}</th>
<th>{Object.keys(graph)[10]}</th>
<th>{Object.keys(graph)[11]}</th>
<th>{Object.keys(graph)[12]}</th>
<th>{Object.keys(graph)[13]}</th>
</tr>
<tr>
<td>{Object.values(graph)[0]}</td>
<td>{Object.values(graph)[1]}</td>
<td>{Object.values(graph)[2]}</td>
<td>{Object.values(graph)[3]}</td>
<td>{Object.values(graph)[4]}</td>
<td>{Object.values(graph)[5]}</td>
<td>{Object.values(graph)[6]}</td>
<td>{Object.values(graph)[7]}</td>
<td>{Object.values(graph)[8]}</td>
<td>{Object.values(graph)[9]}</td>
<td>{Object.values(graph)[10]}</td>
<td>{Object.values(graph)[11]}</td>
<td>{Object.values(graph)[12]}</td>
<td>{Object.values(graph)[13]}</td>
</tr>
</table>
</div>
)
}
As you can see, each entry on the table is a different key/value, and graph represents each individual object in the array. The problem is that some objects have more than 14 keys so I want to list out every key and value in each object within JSX regardless of the size. Does anyone know how to do that? I've tried using for loops (which is usually how I list out individual keys) but I can't seem to do that within JSX.
Use Array.map() for each row. For the th iterate the keys, and for the td use Object.entries() to get both the keys (for the item's keys) and values:
{
data.map(graph => (
<div key={graph.ID} className="tables">
<table>
<tr>
{
Object.keys(graph)
.map(key => <th key={key}>{key}</th>)
}
</tr>
<tr>
{
Object.entries(graph)
.map(([key, val]) => <th key={key}>{val}</th>)
}
</tr>
</table>
</div>
))
}
I think you could do something like this:
{
data.map(graph => {
return (
<div key={graph.ID} className="tables">
<table>
<tr>
{Object.keys(graph).map(key => {
return <th>{key}</th>
})}
</tr>
<tr>
{Object.keys(graph).map(key => {
return <th>{graph[key]}</th>
})}
</tr>
</table>
</div>
)
})
}
You can just use map() method to do this:
<tr>
Object.keys(graph).map((key) => (<th>key</th>))
</tr>
<tr>
Object.values(graph).map((value) => (<td>value</td>))
</tr>
Note: this will most likely complain about absent key props, so you will have to add a key value to each element. (using the key value of graph object is one option)
What I want to do is use Propublica's nonprofit API to pull in information about various nonprofits and display certain attributes in a table.
Right now, I'm fetching an object:
const [ orgs, setOrgs ] = useState({})
const fetchOrgs = async () => {
const result = await Axios.get(`${API_URL}?state%5Bid%5D=${query}`)
setOrgs(result.data.organizations)
}
According to their API, organization objects are like this:
{
"organization":{
"id":142007220,
"ein":142007220,
"name":"PRO PUBLICA INC",
"careofname":null,
"address":"155 AVE AMERICA 13 FL",
"city":"NEW YORK",
"state":"NY",
"zipcode":"10013-0000",
"exemption_number":0,
"subsection_code":3,
"affiliation_code":3,
"classification_codes":"1000",
"ruling_date":"2008-02-01",
"deductibility_code":1,
"foundation_code":15,
"activity_codes":"0",
"organization_code":1,
"exempt_organization_status_code":1,
"tax_period":"2018-12-01",
"asset_code":8,
"income_code":8,
"filing_requirement_code":1,
"pf_filing_requirement_code":0,
"accounting_period":12,
"asset_amount":40988939,
"income_amount":27237842,
"revenue_amount":26685933,
"ntee_code":"A20",
"sort_name":null,
"created_at":"2020-04-13T21:42:55.607Z",
"updated_at":"2020-04-13T21:42:55.607Z",
"data_source":null,
"have_extracts":null,
"have_pdfs":null
},
This is my current function, which is not working:
const displayTable = () => {
return (
<Table striped border='true' hover='true' responsive='true'>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>State</th>
<th>City</th>
<th>NTEE</th>
<th>Income</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>Test</td>
<td>Test</td>
<td>Test</td>
<td>Test</td>
<td><a href=' '>Link</a></td>
</tr>
{Object.keys(orgs).map(({name, state, ntee_code, income_amount}, i) => (
<tr key={i}>
<td>{i + 1}</td>
<td>{name}</td>
<td>{state}</td>
<td>{ntee_code}</td>
<td>{income_amount}</td>
</tr>
))}
</tbody>
</Table>
)
}
When I run this, I get the test row, and then many rows of empty cells. Only the "#" column has anything, since it's just the index value. What am I doing wrong here? Any help would be much appreciated, I've only just started learning React and JS.
here is a working example:
return (
<div>
<h1>Organizations:</h1>
<table style={{ width: '100%', textAlign: 'center', border: 'solid 1px' }}>
<thead>
<th>Index</th><th>Name</th><th>State</th><th>ntee_code</th><th>income_amount</th>
</thead>
<tbody>
{orgs.map((organization, i) => {
const org = organization.organization;
return (
<tr>
<td>{i}</td><td>{org.name}</td><td>{org.state}</td><td>{org.ntee_code}</td><td>{org.income_amount}</td>
</tr>
)
})}
</tbody>
</table>
</div>
)
I'm posting just the returned markup as I understood you have no problem with fetching the data, and you just don't know how to display.
Your solution had the right idea of iterating over the organization array to create <tr>s. But you didn't need the Object.keys() to access the values. You first need to iterate over the objects in the array, and then drill down each object using the . syntax: const org = organization.organization; and then e.g org.name.
Note that each of your objects actually has only one field, i.e organization, so you first need to drill into it and only then you can get the values further down the object tree. If you want to deconstruct the object in map() you can, and again you had the right idea about how it's done, you just got the layer wrong. So you can do
{orgs.map(({organization}, i) => {
const { name, state, ntee_code, income_amount } = organization;
return (
<tr>
<td>{i}</td><td>{name}</td><td>{state}</td><td>{ntee_code}</td><td>{income_amount}</td>
</tr>
)
})}
I hope it can help and it's all clear.
Good luck!
I am trying to implement a table but since I have to iterate through multiple arrays for each row, my items wont get rendered in the correct row or are but the height gets messed up since I don't think I implement the table properly. Could someone please help?
<table id="customers">
<thead>
<tr>
<th>Country</th>
<th>Cities</th>
<th>Shops</th>
<th>Map</th>
</tr>
</thead>
<tbody>
<tr>
<td> {this.renderCountries()}</td>
<td> {this.state.renderCities ? this.renderCities() :
<p>{this.state.defaultCity}</p>} </td>
<td> {this.state.renderShops ? this.renderShops() :
<p>{this.state.defaultShopName}</p>} </td>
<td> {this.state.renderMap ? this.renderMap() : null} </td>
</tr>
</tbody>
</table>
in my methods (renderCountries etc), I iterate through the particular array and return another component
renderCountries = () => {
return this.state.countries.map((country, index) => {
return (
<Column
key={index}
data={country}
/>
)
})
};
const Column = ({data}) => (<p> {data}</p>);
The way I have it so far is the only one that at least renders all items in the correct cell, however, it messes up the CSS (the second row, all items get moved about 200px down), I think its because I m not implementing the table properly, but when I change that to anything else, items wont get rendered correctly. If more info is needed please let me know.