react hooks toggle for specific row - reactjs

Please clarify my problem of toggle for specific row of the table with react hooks. whenever I press click.. it opens for every row and by default the table head is moving right it is not constant.
Error in toggleHidden(key). How to correct my toggleHidden function?
const[isHidden , setIsHidden] = React.useState(true)
const toggleHidden = () => setIsHidden(!isHidden)
const data = [
{
"name": "gvf",
"email": "abc",
"companyname": "xyz",
"address": "abcy"
},
{
"name": "abi",
"email": "dhf",
"companyname": "dhd",
"address": "fhfh"
}
]
return (
<div>
<Row>
<Col>
<table className="table table-hover table-striped table-sm">
<thead className="thead-dark">
<tr>
<th>Name</th>
<th>Email</th>
<th>CompanyName</th>
<th>Address</th>
</tr>
</thead>
<tbody>
{data.map((a , key) => (
<tr key={a.name}>
<td><Button onClick = {toggleHidden(key)}>Click</Button>
{!isHidden && <p>Hello ABIII</p> }
</td>
<td>{a.name}</td>
<td>{a.email}</td>
<td>{a.address}</td>
<td>{a.companyname}</td>
</tr>
))}
</tbody>
</table>
</Col>
</Row> </div>

you need define the specific row - when You mapping:
{data.map(a => (
)}
try add key attribute to every item in collection like this:
{data.map((a, key) => (
))}
then pass to Your item:
<tr key={key}>
So now every is unique - so if You pass that key to your function:
<Button onClick = {toggleHidden(key)}>
the program should know which specific item execute toggleHidden function

Related

Why tankStack React-table render the td tag 2 times after defining which component should render in column

I am facing a weird problem while working with tankStack react-table. I want render some specific tags with extra data. example: i want to render the age column like this (this is the {age})
But don't want to make the tag child of tag but that is happening
Here is my code
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => {
return(
<td key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
)
})
}
</tr>
))}
</tbody>
</table>
Column.js
export const COLUMNS = [
{
header:'First Name',
accessorKey:'first_name',
id:'first_name'
},
{
header:'Last Name',
accessorKey:'last_name',
id:'last_name'
},
{
header:'Age',
accessorKey:'age',
id:'age',
cell: data => <td>this is age{data.getValue()}</td>,
enableGlobalFilter: false,
}
]

How do I display an array where each object in array is a new <td> in ReactJS

I have an array which contains multiple objects like this:
const locations = [
{
information: ["Data Analyst", "Uruguay", "Montevideo", "$30,000"],
},
{
information: ["CTO", "UK", "Manchester", "$75,000"],
}
];
And I want to display each array in a new table row containing a <td> with each string.
Currently I have done this:
<tr>
{locations.map((location) => <td>{location.information}</td>)};
</tr>
Which returns each piece of information on a <td>
This is how the data looks at the minute:
And how it's meant to look
For this you have to use Array.map() like:
// To create tha table body by iterating data array
{
locations.map((location, locationIndex) =>
<tr key={locationIndex}>
<td>{location.information[0]}</td>
<td>{location.information[1]}</td>
<td>{location.information[2]}</td>
<td>{location.information[3]}</td>
</tr>
)
}
// In case you don't want to harcode the array index
{
locations.map((location, locationIndex) =>
<tr key={locationIndex}>
location.information.map((loc, locIndex) =>
<td key={locIndex}>{loc}</td>
)
</tr>
)
}
Change the code from,
<tr>
{locations.map((location) => <td>{location.information}</td>)};
</tr>
To:
<table border="1" width="100%" className="component_useRefBox">
<tbody>
{locations.map((location, i) => {
return (
<tr key={i}>
{location.information.map((data, j) => {
return <td key={j}> {data} </td>;
})}
</tr>
);
})}
</tbody>
</table>
To display two records row by row, you need to move {locations.map((location) .... )} above <tr> ... </tr> tag, because while using map method only each row will get iterated and you will get two separate rows..
{locations.map((location, i) => {
return (
<tr>
....
</tr>
)})}
As location.information is of array data, you cannot assign it directly.
You need to iterate using map and display each data like,
{location.information.map((data) => {
return <td> {data} </td>;
})}

How To Conditional Render Data From 2 Data Sources Using React

I am rendering data from two JSON files in react. First file is my main file and from the second file I want conditional rendering on the basis of the first file.
Explanation: From First file name "maindata.json" I am rendering all the data into a table. There is a Unique id field in the Json in first file. From Second file I just want to populate only a date fieldand there is also a unique id in the second JSON. What I want is if the main JSon file id matches with the id in the second json file, so print the date from the second file in the same row next to the id from the main file.
What I have done.
I have applied the condition but the problem is its not doing the match and prints all the dates in one column.
React App is getting slower ( performance Issue )
Here is my Code sample.
import React, { Component } from "react";
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import ReactHTMLTableToExcel from 'react-html-table-to-excel';
import data from "./data/maindata.json";
import data1 from "./data/data2.json";
class PenApprovals extends Component {
render() {
return (
<div className="container-fluid" style={{ backgroundColor: '#f7f7f7' }}>
<table id="table-to-xls" className="table table-responsive table-striped display nowrap" >
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Date</th>
<th scope="col">Status</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{data.map((record) => (
<tr>
<td>{record.UniqueName}</td>
<td>
{data1.map((item) =>
<React.Fragment>
//Here fetching date from second file
{item.uniqueName === <span>{record.UniqueName}</span> ? <span>
{item.assignedDate}</span> : "NO Match Found" }
</React.Fragment>
)}
</td>
<td>{record.Status }</td>
<td>{record.Name}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}
export default PenApprovals;
here is JSON Sample.
Main Data File
[
{
"UniqueName": "CR30876",
"StatusString": "Submitted",
"Name": "Pegasus Test 1"
},
{
"UniqueName": "CR35876",
"StatusString": "Submitted",
"Name": "Pegasus Test 1"
}
]
Second Conditional JSON File sample
[
{
"uniqueName": "CR35876",
"assignedDate": "2020-11-09",
},
{
"uniqueName": "CR34523",
"assignedDate": "2020-11-09",
}
//More records....
]
Thanks Everyone.
You should use filter instead of map! Here's the code that works.
class PenApprovals extends Component {
render() {
return (
<div className="container-fluid" style={{ backgroundColor: "#f7f7f7" }}>
<table
id="table-to-xls"
className="table table-responsive table-striped display nowrap"
>
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Date</th>
<th scope="col">Status</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{data.map((record) => {
const tgt = data1.filter(
(item) => item.uniqueName === record.UniqueName
);
return (
<tr>
<td>{record.UniqueName}</td>
<td>
{tgt.length
? tgt.map((item) => (
<React.Fragment key={item.uniqueName}>
<span>{item.assignedDate}</span>
</React.Fragment>
))
: "NO Match Found"}
</td>
<td>{record.StatusString}</td>
<td>{record.Name}</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
}
export default PenApprovals;

Toggle specific row with hooks

Error in toggleHidden(key) [error: expecting 0 args but got 1] . kindly suggest corrections top toggle with key for particular row.
code
const [isOpen, setIsOpen] = React.useState(false);
const toggle = () => setIsOpen(!isOpen);
const[isHidden , setIsHidden] = React.useState(true)
const toggleHidden = () => setIsHidden(!isHidden)
const data = [
{
"name": "gvf",
"email": "abc",
"companyname": "xyz",
"address": "abcy"
},
{
"name": "abi",
"email": "dhf",
"companyname": "dhd",
"address": "fhfh"
}
]
return (
<div>
<Row>
<Col>
<table className="table table-hover table-striped table-sm">
<thead className="thead-dark">
<tr>
<th>Name</th>
<th>Email</th>
<th>CompanyName</th>
<th>Address</th>
</tr>
</thead>
<tbody>
{data.map((a , key) => (
<tr key={key}>
<td><Button onClick = {toggleHidden}>Click</Button>
{!isHidden && <p>Hello ABIII</p> }
</td>
<td>{a.name}</td>
<td>{a.email}</td>
<td>{a.address}</td>
<td>{a.companyname}</td>
</tr>
))}
</tbody>
</table>
</Col>
)
}
Just change the state to be an array and "pop"/"push" keys into it on toggle, then declare a curried handler that accepts a key, and performs proper toggle logic. I removed isOpen state since it was not used in the example, however you can change it the same way that isHidden state and toggler was changed:
const [ isHiddenList, setIsHiddenList ] = React.useState([])
const toggleHidden = key => () => {
setIsHiddenList(
isHiddenList.includes(key)
? isHiddenList.filter(existingKey => existingKey !== key)
: [ ...isHiddenList, key ]
);
};
const data = [
{
"key": "1"
"name": "gvf",
"email": "abc",
"companyname": "xyz",
"address": "abcy"
},
{
"key": "2"
"name": "abi",
"email": "dhf",
"companyname": "dhd",
"address": "fhfh"
}
]
return (
<div>
<Row>
<Col>
<table className="table table-hover table-striped table-sm">
<thead className="thead-dark">
<tr>
<th>Name</th>
<th>Email</th>
<th>CompanyName</th>
<th>Address</th>
</tr>
</thead>
<tbody>
{
data.map(({ key, name, email, companyname, address }) => {
const isHidden = isHiddenList.includes(key);
return (
<tr key={key}>
<td><Button onClick={toggleHidden(key)}>Click</Button>
{!isHidden && <p>Hello ABIII</p> }
</td>
<td>{a.name}</td>
<td>{a.email}</td>
<td>{a.address}</td>
<td>{a.companyname}</td>
</tr>
);
})
}
</tbody>
</table>
</Col>
</Row>
</div>
)
disclaimer - key should be part of data items for consistency, dynamically generated iteration index does not guarantee that keys will be assigned properly.

How can I render data within nested objects in react?

I am working with an API that contains nested objects and I am not sure how to display it. I am reading about using Object.keys but not sure how to do it... help please...
Here is the react code. I need to render prices dynamically.
<div>
<Table responsive striped bordered hover variant="dark">
<thead>
<tr>
<th>Rank</th>
<th>Name</th>
<th>Symbol</th>
<th>Price</th>
<th>% Change</th>
<th>Market Cap</th>
</tr>
</thead>
<tbody>
{Object.keys(
cryptos.map(crypto => (
<tr key={crypto.id}>
<td>{crypto.cmc_rank}</td>
<td>
<Link to={`/crypto/${crypto.id}`}>{crypto.name}</Link>
</td>
<td>{crypto.symbol}</td>
<td>{`price should be displayed here `}</td>
<td>{`price change should be displayed here `}</td>
<td>{`market cap should be displayed here `}</td>
</tr>
))
)}
</tbody>
</Table>
</div>
Here is the data source
"data": [
{
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
"slug": "bitcoin",
"num_market_pairs": 8203,
"date_added": "2013-04-28T00:00:00.000Z",
"tags": [
"mineable"
],
"max_supply": 21000000,
"circulating_supply": 18376356,
"total_supply": 18376356,
"platform": null,
"cmc_rank": 1,
"last_updated": "2020-05-13T10:30:30.000Z",
"quote": {
"USD": {
"price": 8920.68810523,
"volume_24h": 40828691066.513,
"percent_change_1h": 0.107841,
"percent_change_24h": 1.62343,
"percent_change_7d": -2.5838,
"market_cap": 163929740386.67194,
"last_updated": "2020-05-13T10:30:30.000Z"
}
}
},
Here you go with a solution
<div>
<Table responsive striped bordered hover variant="dark">
<thead>
<tr>
<th>Rank</th>
<th>Name</th>
<th>Symbol</th>
<th>Price</th>
<th>% Change</th>
<th>Market Cap</th>
</tr>
</thead>
<tbody>
{
cryptos.length &&
cryptos.map(crypto => (
<tr key={crypto.id}>
<td>{crypto.cmc_rank}</td>
<td>
<Link to={`/crypto/${crypto.id}`}>{crypto.name}</Link>
</td>
<td>{crypto.symbol}</td>
<td>{crypto.quote.USD.price}</td>
<td>{crypto.quote.USD.price * crypto.quote.USD.percent_change_1h}</td>
<td>{crypto.quote.USD.market_cap}</td>
</tr>
)
)}
</tbody>
</Table>
</div>
Here is the data source
"data": [
{
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
"slug": "bitcoin",
"num_market_pairs": 8203,
"date_added": "2013-04-28T00:00:00.000Z",
"tags": [
"mineable"
],
"max_supply": 21000000,
"circulating_supply": 18376356,
"total_supply": 18376356,
"platform": null,
"cmc_rank": 1,
"last_updated": "2020-05-13T10:30:30.000Z",
"quote": {
"USD": {
"price": 8920.68810523,
"volume_24h": 40828691066.513,
"percent_change_1h": 0.107841,
"percent_change_24h": 1.62343,
"percent_change_7d": -2.5838,
"market_cap": 163929740386.67194,
"last_updated": "2020-05-13T10:30:30.000Z"
}
}
},
Price changed I have considered percent_change_1h * price. Check for cryptos.length before doing map operation.
I have no idea why you have {Object.keys( in there... remove it.
<div>
<Table responsive striped bordered hover variant="dark">
<thead>
<tr>
<th>Rank</th>
<th>Name</th>
<th>Symbol</th>
<th>Price</th>
<th>% Change</th>
<th>Market Cap</th>
</tr>
</thead>
<tbody>
{ cryptos.map(crypto => (
<tr key={crypto.id}>
<td>{crypto.cmc_rank}</td>
<td>
<Link to={`/crypto/${crypto.id}`}>{crypto.name}</Link>
</td>
<td>{crypto.symbol}</td>
<td>{`price should be displayed here `}</td>
<td>{`price change should be displayed here `}</td>
<td>{`market cap should be displayed here `}</td>
</tr>
)) }
</tbody>
</Table>
</div>
Having Object.keys() essentially returns an array containing the indexes of the array you map from cryptos. React needs an array of elements, so you just need iterate through the elements of cryptos, and map each item to something React can render.
For example:
const dataList = [{ key:'a', value:'Hello' }, { key:'b', value:'World' }];
<div>
{ dataList.map(data => <div key={ data.key }>{ data.value }</div>) }
</div>
Will render
<div>
<div>Hello</div>
<div>World</div>
</div>

Resources