I have multiple with the same class name and method with different parameter
i want to refactor the below code to a simpler way any suggestion would be helpful.
<table class="greyGridTable">
<tbody>
<tr>
<td>AA</td>
<td className = 'table-container'>{formatDate(someMethod1(param1,a)}</td>
</tr>
<tr>
<td>BB</td>
<td className = 'table-container'>{formatDate(someMethod1(param1,b)}</td>
</tr>
<tr>
<td>CC</td>
<td className = 'table-container'>{formatDate(someMethod1(param1,c)}</td>
</tr>
</tbody>
</table>
I want to refactor the code with the same component.
I hope this would be helpful. thanks
export const TableItems = ({data}) => {
return (
<>
{data.map(item => (
<tr>
<td>{item.name}</td>
<td className='table-container'> {item?.symbol} {formatDate(someMethod1(param1,a)}</td>
</tr>
))}
</>
)
}
const data = [
{
name: AA,
},
{
name: BB,
},
{
name: CC,
symbol: '£'
}
]
<table class="greyGridTable">
<tbody>
<TableItems data={data} />
</tbody>
</table>
Try to use an array instead. Having reusable components in an array is easy to maintain, expand and read. Definitely a good practice.
let tableItems = [{name:"AA",date:new Date()},.....]
return (
<table class="greyGridTable">
<tbody>
{tableItems.map((item,index)=>{
return(
<tr>
<td>{item.date}</td>
<td className = 'table-container'>{item.date}</td>
</tr>
)
})}
</tbody>
</table>
)
Related
I am trying to build one table using props, and pass the value from that table to another function. But for some reason, the result is not displaying. What have I done wrong?
import Table from "https://cdn.skypack.dev/react-bootstrap#2.5.0";
function Tables(props) {
return (
<Table>
<thead>
<tr>
<th>a</th>
<th>b</th>
<th>c</th>
</tr>
</thead>
<tbody>
<tr>
<td>{props.first}</td>
<td>{props.second}</td>
<td>{props.third}</td>
</tr>
</tbody>
</Table>
)
}
function App() {
return (
<div>
<Tables first="Sara" />
<Tables second="Cahal" />
<Tables third="Edite" />
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
You are rendering the table three times, each one with only one prop, you need to
If you want to show one table with the three props, it should be like that.
import Table from "https://cdn.skypack.dev/react-bootstrap#2.5.0";
function Tables(props) {
return (
<Table>
<thead>
<tr>
<th>a</th>
<th>b</th>
<th>c</th>
</tr>
</thead>
<tbody>
<tr>
<td>{props.first}</td>
<td>{props.second}</td>
<td>{props.third}</td>
</tr>
</tbody>
</Table>
)
}
function App() {
return (
<div>
<Tables first="Sara" second="Cahal" third="Edite" />
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
import React from 'react';
export default class HelloWorld extends React.Component {
public render(): JSX.Element {
let elements = [{"id":1,"isActive":true,"object":"Communication","preview":"Un appercu de la communication","sentAt":{"date":"2020-12-17 15:18:46.000000","timezone_type":3,"timezone":"Europe\/Paris"},"url":"\/\/30osd.r.a.d.sendibm1.com\/mk\/mr\/kwK4UoPBwpKUgtMy3RrTs3Fn0Zn0hb4lTgoZcAqRkeWesC3OtK_zelPOf4zHvGR7XP1gto1uuSmJUtNuOUTFtcLqgnHofc_mOiocZLAtwg5XdfRW"}];
return (
<table>
<thead>
<tr>
<th>Elements</th>
<th>Contenu</th>
</tr>
</thead>
<tbody>
{elements.map(element => {
<tr>
<td>
<p>{element.id}</p>
</td>
<td>
<p>{element.url}</p>
</td>
</tr>
})}
</tbody>
</table>
);
}
}
Why nothing is printed inside the tbody of the table ?
I don't know why I'm over it for 2 hours
I want one tr per element and also in each tr have one td for element.id and one for element.url
Inside tbody it should be:
<tbody>
{elements.map(element => {
return <tr>
<td>
<p>{element.id}</p>
</td>
<td>
<p>{element.url}</p>
</td>
</tr>
})}
</tbody>
Try wrapping your elements in parentheses.
An alternative to Sakshi's answer would be:
{
elements.map((element) => (
<tr>
<td>
<p>{element.id}</p>
</td>
<td>
<p>{element.url}</p>
</td>
</tr>
));
}
Make sure you return the JSX elements in your array's .map(). You can use implicit or explicit return:
<tbody>
{elements.map((element) => (
<tr>
<td>
<p>{element.id}</p>
</td>
<td>
<p>{element.url}</p>
</td>
</tr>
))}
</tbody>
Or:
<tbody>
{elements.map((element) => {
return (
<tr>
<td>
<p>{element.id}</p>
</td>
<td>
<p>{element.url}</p>
</td>
</tr>
);
})}
</tbody>
first remove the JSX.Element from the render method as it's not needed if you've created your app with npm create, the main thing is that you need to return your table row inside map function(you only have one row at the moment).
import React from 'react';
export default class HelloWorld extends React.Component {
render(){
let elements = [{"id":1,"isActive":true,"object":"Communication","preview":"Un appercu de la communication","sentAt":{"date":"2020-12-17 15:18:46.000000","timezone_type":3,"timezone":"Europe\/Paris"},"url":"\/\/30osd.r.a.d.sendibm1.com\/mk\/mr\/kwK4UoPBwpKUgtMy3RrTs3Fn0Zn0hb4lTgoZcAqRkeWesC3OtK_zelPOf4zHvGR7XP1gto1uuSmJUtNuOUTFtcLqgnHofc_mOiocZLAtwg5XdfRW"}];
return (
<table>
<thead>
<tr>
<th>Elements</th>
<th>Contenu</th>
</tr>
</thead>
<tbody>
{elements.map(element => {
return(
<tr>
<td>
<p>{element.id}</p>
</td>
<td>
<p>{element.url}</p>
</td>
</tr>
)
})}
</tbody>
</table>
);
}
}
I want to set a unique id for each MenuItem, but I don't know how to do this with map() function nested in another one
<table className={classes.table}>
<thead>
<tr>
<td />
{sit.sit.map(sit => (
<td className={classes.sitCell} align="center" key={sit}>
{sit}
</td>
))}
</tr>
</thead>
<tbody>
{sit.row.map(row => (
<tr key={row}>
<td className={classes.rowCell} align="left">
{row}
</td>
{sit.sit.map(sit => (
<td className={classes.sit} key={(id = id + 1)}>
<MenuItem
id={sitId}
onClick={handleSitClick}
disabled={selected}
className={classes.sit}
/>
</td>
))}
</tr>
))}
</tbody>
</table>
Provided code looks fine for me. You can use uuid or any other similar package to generate keys.
Your question is not fully clear i think its may be help you .
<table className={classes.table }>
<thead>
<tr>
<td></td>
{
sit.sit.map((sit) => (<td className={classes.sitCell} align='center' key={sit}>{sit}</td>))
}
</tr>
</thead>
<tbody>
{
sit.row.map((row,index )=> (
<tr key={index}>
<td className={classes.rowCell} align='left'>{row}</td>
{
sit.sit.map((sit) => (<td className={classes.sit} key={id = id+1}><MenuItem id={sitId} onClick={handleSitClick} disabled={selected} className={classes.sit}></MenuItem></td>))
}
</tr>
))
}
</tbody>
</table>
you can just add (row,index) like this
Ideally you need to use a key which is some kind of unique id from your api response. Check your api response data structure, if it has an unique id, then use it. Else use the map array index.
Like this
<table className={classes.table}>
<thead>
<tr>
<td></td>
{
sit.sit.map((sit) => (<td className={classes.sitCell} align='center' key={sit}>{sit}</td>))
}
</tr>
</thead>
<tbody>
{
sit.row.map(row => (
<tr key={row}>
<td className={classes.rowCell} align='left'>{row}</td>
{
sit.sit.map((sit, index) => (<td className={classes.sit} key={index}><MenuItem id={index} onClick={handleSitClick} disabled={selected} className={classes.sit}></MenuItem></td>))
}
</tr>
))
}
</tbody>
</table>
I have this code in my render function, but I have 5 different versions with minor html changes. I made new tables with each of the 5. How would I optimize it so I do not have to repeat a lot of html/js code?
<table>
<thead>
<tr>
<th></th>
<th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody> { this.showData
this.state.data.map((exp) => {
if (exp.typeOfItem === "Asset" && exp.term == "Short-Term" ) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{exp.description}</td>
<td className='button-col'>${exp.amount}</td>
<td className='button-col'>
<Update expense={exp} />
</td>
<td className='button-col'>
<Delete expense={exp} />
</td>
</tr>
}
})
}
</tbody>
</table>
<table>
<thead>
<tr>
<th></th>
<th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody>
{
this.state.data.map((exp) => {
if (exp.typeOfItem === "Asset" && exp.term == "Long-Term" ) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{exp.description}</td>
<td className='button-col'>${exp.amount}</td>
<td className='button-col'>
<Update expense={exp} />
</td>
<td className='button-col'>
<Delete expense={exp} />
</td>
</tr>
}
})
}
</tbody>
</table>
You can pull out your Table in a custom component and pass down the data as props,
Your new component would be,
import React from 'react'
const TableComponent = (props) => (
<table>
<thead>
<tr>
<th></th><th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody>
{
props.data.map((exp) => {
if (exp.typeOfItem === props.typeOfItem && exp.term === props.term ) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{exp.description}</td>
<td className='button-col'>${exp.amount}</td>
<td className='button-col'> <Update expense={exp}/></td>
<td className='button-col'><Delete expense={exp} /></td>
</tr>
}
})
}
</tbody>
</table>
)
export default TableComponent
Now you can render this component by passing props,
<TableComponent data={this.state.data} typeOfItem="Asset" term="Short-Term"/>
<TableComponent data={this.state.data} typeOfItem="Asset" term="Long-Term"/>
Note: If you have any other variable's to be used in Table, do pass them as props and in your TableComponent use them appropriately.
You would be better off splitting the array before the render.
for instance:
const assets = this.state.data.filter(item => item.typeOfItem === "Asset");
const longTerm = [];
const shortTerm = [];
assets.forEach((asset) => {
asset.term = "long" ? longTerm.push(asset) : shortTerm.push(asset);
});
Next you can render it with a component you want
longTerm.map(asset => {
return <MyComponent amount={asset.amount} ... />
})
shortTerm.map(asset => {
return <MyComponent amount={asset.amount} ... />
})
And your component could be
function MyComponent(props) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{props.description}</td>
//rest
</tr>
}
additionally you could make a table component and pass it the collection which calls MyComponent
function TableComponent({collection}) {
return <table>
<thead>
<tr>
<th></th><th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody>
{
collection.map(asset => {
return <MyComponent ....
});
}
</tbody>
</table>
}
and then the initial render would just be
<>
<TableComponent collection={longterm} />
<TableComponent collection={shortterm} />
</>
I am trying to create a dynamic table, using this example- Dynamic & Complex rowspan in HTML table
I am trying to replicate the similar thing in react.js
I have put a closing tr tag in conditional rendering if the index is 0.
However, it gives me ' Expected corresponding JSX closing tag for <>'
The state 'data' object which I got from back-end is something like -
{
"100": [
"ABC"
],
"101": [
"123",
"DEF",
"XYZ",
"456",
"657",
"1234",
"4564",
"vdfgx",
"vcegefgg",
"g544"
]
}
I have written following code in component to create dynamic table.
<table>
<thead>
<tr>
<th>Code</th>
<th>Reason</th>
</tr>
</thead>
<tbody>
{Object.keys(this.state.data).map(
(error_code, i) => {
return (
<React.Fragment>
<tr>
<td
rowSpan={
this.state.data[
error_code
].length
}
key={i}
>
{error_code}
</td>
{this.state.data[
error_code
].map((error_description, index) => (
<React.Fragment>
{index === 0 ? (
<React.Fragment>
<td
key={index}
rowSpan="1"
>
{error_description}
</td>
</tr> //<--- HERE
</React.Fragment>
) : (
<tr>
<td
key={index}
rowSpan="1"
>
{error_description}
</td>
</tr>
)}
</React.Fragment>
))}
</React.Fragment>
);
}
)}
</tbody>
</table>
I want the final output something like -
<tbody>
<tr>
<td rowspan="1">100</td>
<td rowspan="1">ABC</td>
</tr>
<tr>
<td rowspan="10">101</td>
<td rowspan="1">123</td>
</tr>
<tr>
<td rowspan="1">DEF</td>
</tr>
<tr>
<td rowspan="1">XYZ</td>
</tr>
<tr>
<td rowspan="1">456</td>
</tr>
.....
</tbody>
Could anyone please guide me the correct way to achieve the desired output ?
JSX, like XML, requires proper nesting <><tr>...</tr></> and does not support overlapping tags like <><tr></></tr>. You need to structure your code in a way to preserve proper nesting:
<tbody>
{Object.keys(this.state.data).map((error_code, i) => {
return this.state.data[error_code].map((error_description, index) =>
index === 0 ? (
<tr>
<td rowSpan={this.state.data[error_code].length} key={i}>
{error_code}
</td>
<td key={index} rowSpan="1">
{error_description}
</td>
</tr>
) : (
<tr>
<td key={index} rowSpan="1">
{error_description}
</td>
</tr>
)
)
})}
</tbody>
JSX does not generate a string. It generates a tree-like structure built out of function calls and Objects. Any <tag></tag> translates into a function call, that's why your code is invalid.
You need to rethink this component.
Split the data processing and decision making into a separate function that does only that and returns the final data to be rendered. Then loop/map through it in render and return the elements structure.