React not displaying data in table row - reactjs

I am a beginner to React and frontend development in general.
Here is a "simple" code to display a table.
function TableHeader() {
return (
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
);
}
function TableDataRow(row, index) {
return (
<tr key={index}>
<td>{row.name}</td>
<td>{row.job}</td>
</tr>
)
}
function TableBody(props) {
const characterData = props.characterData;
return (
<tbody>
{characterData.map((row, index) => <TableDataRow row={row} index={index}/>)}
</tbody>
);
}
class Table extends Component {
render() {
const { characterData } = this.props;
return (
<table>
<TableHeader />
<TableBody characterData={characterData} />
</table>
);
}
}
class App extends Component {
render() {
const characters = [
{
'name': 'Charlie',
'job': 'Janitor'
},
{
'name': 'Mac',
'job': 'Bouncer'
},
{
'name': 'Dee',
'job': 'Aspring actress'
},
{
'name': 'Dennis',
'job': 'Bartender'
}
];
return (
<div className="container">
<Table characterData={characters} />
</div>
);
}
}
The error is as follows:
Warning: Each child in a list should have a unique "key" prop.
Check the render method of TableBody. See
https://banned-fb.example.com/react-warning-keys for more information.
in TableDataRow (at Table.js:30)
in TableBody (at Table.js:44)
in table (at Table.js:42)
in Table (at App.js:28)
in div (at App.js:27)
in App (at src/index.js:6)
The data rows are empty in the table. I think there is an issue in the call to TableDataRow. What is that I am possibly doing wrong?
Screenshot:

Key thing is just a warning, but you should fix it too, the reason nothing is rendering because you have your component like this:
function TableDataRow(row, index) {...} // WRONG
Function Component get just one argument that is props, what you need to do is either:
function TableDataRow(props) {
const {row, index} = props; // get row and index out of props inside function
...
}
OR
function TableDataRow({ row, index }) {...} // destructure the props in parameter
Now About fixing the key warning:
Instead of providing key to the <tr> inside TableDataRow you need to provide key to TableDataRow, like this:
function TableDataRow({ row }) { // you have a little error here too, row should be inside curly braces or use props and get row from props inside the function
return (
<tr> // no need of key
<td>{row.name}</td>
<td>{row.job}</td>
</tr>
)
}
function TableBody(props) {
const characterData = props.characterData;
return (
<tbody>
{characterData.map((row, index) => <TableDataRow row={row} key={index}/>)} // key should be here
</tbody>
);
}
Also you should use index as key as last resort (see docs for why). If your data comes from api every item might have an id you can use that as key, or there is maybe something else unique for each character, if not, it's ok to use index.

import React from 'react';
function TableHeader() {
return (
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
);
}
function TableBody(props) {
const characterData = props.characterData;
return (<tbody>
{characterData.map((row, index) =>
<tr key={index}>
<td>{row.name}</td>
<td>{row.job}</td>
</tr>)}
</tbody>
);
}
class Table extends React.Component {
render() {
const { characterData } = this.props;
return (
<table>
<TableHeader />
<TableBody characterData={characterData} />
</table>
);
}
}
class Hello extends React.Component {
render() {
const characters = [
{
'name': 'Charlie',
'job': 'Janitor'
},
{
'name': 'Mac',
'job': 'Bouncer'
},
{
'name': 'Dee',
'job': 'Aspring actress'
},
{
'name': 'Dennis',
'job': 'Bartender'
}
];
return (
<div className="container">
<Table characterData={characters} />
</div>
);
}
}
export default Hello;
Find your working solution here..
Stackblitz Link

Related

Display fetched data into table in React

I am unable to tel why my table has no data. Is it the way I'm calling for the display, {this.newItems} or what could it be?
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
taskList: []
};
}
componentDidMount() {
this.refreshList();
}
//refreshList Function start
refreshList = () => {
axios
.get("http://127.0.0.1:8000/list/api/rooms/")
.then(res => this.setState({ taskList: res.data }))
.catch(err => alert(err))
}
//refreshList Function end
//renderItems Function start
renderItems = () => {
const newItems = this.state.taskList;
return newItems.map(item => (
<tr key={item.id}>
<td>{item.thing1}</td>
<td>{item.thing2}</td>
<td>{item.thing3}</td>
</tr>
));
};
//renderItems Function end
render (){
return (
<div>
<Navbar/>
<table className="layout container">
<thead>
<tr>
<th>thing1</th>
<th>thing2</th>
<th>thing3</th>
</tr>
</thead>
<tbody>
{this.newItems}
</tbody>
</table>
<Footer/>
</div>
)
}
}
The reason is that inside <tbody> tag you are using this.newItems, which is a local variable and doesn't exist outside the scope of renderItems function.
The piece of code responsible to render the table data is renderItems function, which you created but never called.
So you just need to do that:
<tbody>
{this.renderItems()}
</tbody>
Also, inside the renderItems function, there is no need to create additional variable if you are not going to modify it. So it can be written simply as:
renderItems = () => {
return this.state.taskList.map(item => (
<tr key={item.id}>
<td>{item.thing1}</td>
<td>{item.thing2}</td>
<td>{item.thing3}</td>
</tr>
));
};

How to display the list response which inside the object - react js

How to display the data in the below from the below json.
{
"a":
{
"b":[
{"id":"ef718cce-1269-4fbd-827c-832f7824c025","name":"Veera6"},
{"id":"0cda5ae9-e287-4666-804a-03f25e642d1f","name":"Veera9"},
{"id":"31f8f042-dbc0-4dbf-ada8-b94c7e2d2a39","name":"Veera8"},
{"id":"6292054c-8bfc-4d2d-b2f8-92e2bac5a578","name":"Veera7"},
{"id":"c6756e5c-8fa5-40a9-ab92-5242bda97de3","name":"Veera10"}]
}
}
code snipped below.
render() {
return (
<table>
<thead>
<tr>
{
this.headers.map(function(h) {
return (
<th key = {h.key}>{h.label}</th>
)
})
}
</tr>
</thead>
<tbody>
{
this.state.tags.b.map(function(item, key) {
return (
<tr key = {key}>
<td>{item.id}</td>
<td>{item.name}</td>
</tr>
)
})
}
</tbody>
</table>
)
}
}
How to display the data in table. Here i need to get the array/list b. Tried different approaches to get the data from the object array but no luck.
Don't know what you were going to do in first < tr >.
Maybe this will point you to the right direction.
import React from "react";
import "./styles.css";
const headers = {
a: {
b: [
{ id: "ef718cce-1269-4fbd-827c-832f7824c025", name: "Veera6" },
{ id: "0cda5ae9-e287-4666-804a-03f25e642d1f", name: "Veera9" },
{ id: "31f8f042-dbc0-4dbf-ada8-b94c7e2d2a39", name: "Veera8" },
{ id: "6292054c-8bfc-4d2d-b2f8-92e2bac5a578", name: "Veera7" },
{ id: "c6756e5c-8fa5-40a9-ab92-5242bda97de3", name: "Veera10" }
]
}
};
let keys = Object.getOwnPropertyNames(headers.a.b[0]);
let head = keys.map(propertyName => <th key={propertyName}>{propertyName}</th>);
export default function App() {
return (
<table>
<thead>
<tr>{head}</tr>
</thead>
<tbody>
{headers.a.b.map(function(item, key) {
return (
<tr key={key}>
<td>{item.id}</td>
<td>{item.name}</td>
</tr>
);
})}
</tbody>
</table>
);
}
So you should access b with headers.a.b and then map().
Your b array is nested inside the headers a object, which is nested in headers object.
Result will be:
id name
ef718cce-1269-4fbd-827c-832f7824c025 Veera6
0cda5ae9-e287-4666-804a-03f25e642d1f Veera9
31f8f042-dbc0-4dbf-ada8-b94c7e2d2a39 Veera8
6292054c-8bfc-4d2d-b2f8-92e2bac5a578 Veera7
c6756e5c-8fa5-40a9-ab92-5242bda97de3 Veera10
Also be sure to check sandbox demo out.
Try this once :
{
this.state.tags.a.b.map(function(item, key) {
return (
<tr key = {key}>
<td>{item.id}</td>
<td>{item.name}</td>
</tr>
)
})
}
Hope it helps. feel free for doubts
Try this
this.state.tags.a.b.map
import React from 'react';
import './App.css';
import { useQuery } from '#apollo/react-hooks';
import gql from "graphql-tag";
const GET_GRPHQL_API = gql`
{
getTags
{
id
tagName
tagDesc
tagVersion
tagVersion
}
}
`
function App() {
const { data, loading, error } = useQuery(GET_GRPHQL_API);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
return (
<React.Fragment>
<table>
<thead>
</thead>
<tbody>
{data &&
data.getTags &&
data.getTags.map(function(item, key) {
return (
<tr key={key}>
<td>{item.id}</td>
<td>{item.tagName}</td>
<td>{item.tagDesc}</td>
<td>{item.tagVersion}</td>
</tr>
);
})}
</tbody>
</table>
</React.Fragment>
);
}
export default App;

Not able to render the new component on onClick()

I am new to react and facing some problem while rendering a new component on onClick() on a table cell item.
class Component extends React.Component{
constructor(props) {
super(props);
this.routeChange = this.routeChange.bind(this)
this.state = {
values: []
};
}
routeChange(id) {
console.log(id)
const userAccount = (
<Account />
);
return userAccount;
}
render() {
return (
<div className="classname1">
<table>
<thead className="table-header">
<tr className="table-row">
<th>Account Name</th>
</tr>
</thead>
<tbody>
{this.state.values.map(value => {
return (
<tr className="data-table">
<td className="txt-blue" onClick={() => this.routeChange(value.id)}>{value.name}</td>
</tr>)
})}
</tbody>
</table>
</div>
}
So when I execute the above everything works fine and the table has been rendered properly but when I click on the table cell item then my component is not being rendered. But I can see the console.log() which I have passed in routeChange().
Note: My state values[] is not empty because as here I am only showing the snippet of my code.
You need to pass a reference of a function that calls routeChange function to the onClick function. One way to do this is to use an arrow function.
<td className="txt-blue" onClick={() => this.routeChange(values.value.id)}>{values.value.name}</td>
When you click and the event 'onClick' is triggered, it doesn't expect a return value, meaning that component you are returning is going nowhere.
What you can do to show the 'Account' component is keep a variable, say showAccount, in your state, which initialises as false, and with the method 'routeChange' what you do is change this to true.
I don't quite understand your use case, but something like this could be:
class Component extends React.Component{
constructor(props) {
super(props);
this.routeChange = this.routeChange.bind(this)
this.state = {
values: [],
accountId: null,
showAccount: false
};
}
routeChange(id) {
console.log(id)
/* Commenting this,
const userAccount = (
<Account />
);
return userAccount;
*/
this.setState({showAccount: true, accountId: id})
}
render() {
return (
<div className="classname1">
<table>
<thead className="table-header">
<tr className="table-row">
<th>Account Name</th>
</tr>
</thead>
<tbody>
{this.state.values.map(value => {
return (
<tr className="data-table">
<td className="txt-blue" onClick={() => this.routeChange(value.id)}>{value.name}</td>
</tr>)
})}
</tbody>
</table>
{this.state.showAccount && this.state.accountId &&
<Account id={this.state.accountId} />
}
</div>
}
Anyhow, try to play with your component and see what works best for you. What I suggest may not be useful for you, so just take the concept and adapt it for your own app.

Creating a component in react and typescript

I am trying to convert this table below from react to typescript. I want to make it universal table component where I can use for every data. This is a sample a table I created in react and its working well. In typescript, the class experts an interface which I have been finding it difficult to apply here.The table must be able to accept data from a webservice and display at any point in time. What am I supposed to add.
class Table extends Component {
render() {
const { characterData, removeCharacter } = this.props;
return (
<table className="table-bordered table-striped">
<TableHeader />
<TableBody characterData={characterData}
removeCharacter={removeCharacter}
/>
</table>
);
}
}
const TableHeader = () => {
return (
<thead>
<tr>
<th width="300">Name</th>
<th width="300">Job</th>
<th width="300">Date</th>
</tr>
</thead>
);
}
const TableBody = props => {
const rows = props.characterData.map((row, index) => {
return (
<tr key={index}>
<td >{row.name}</td>
<td >{row.job}</td>
<td >{row.date}</td>
<td><button onClick={() => props.removeCharacter(index)}>Delete</button></td>
</tr>
);
});
return <tbody>{rows}</tbody>;
}
export default Table;
You can type check your props by adding chevrons next to the Component prototype. The first argument is type checking your props and the second argument will type check your internal state.
interface TableProps {
characterData: //...however the data should be structured
removeCharacter: () => void;
}
interface TableState {
//... this is empty because you haven't defined any internal component state
}
class Table extends Component<TableProps, TableState> {
render() {
const { characterData, removeCharacter } = this.props;
return (
<table className="table-bordered table-striped">
<TableHeader />
<TableBody characterData={characterData}
removeCharacter={removeCharacter}
/>
</table>
);
}
}

Iterate through a dictionary with React to construct a Table

I want to iterate a dictionary to construct a table using React, but I am stuck with this error:
PricingPlanTable.jsx:33 Uncaught TypeError: Cannot read property 'map'
of undefined
Here's my code:
BillingAccount.jsx
import React, { PropTypes, Component } from 'react';
import PricingPlanTable from './PricingPlanTable';
export default class BillingAccount extends React.Component {
render() {
var pricingPlans = {
'planNames': ['Starter', 'Bronze', 'Silver', 'Gold', 'Enterprise'],
'planPrices': ['free', '$10', '$25', '$49', 'Contact Us'],
'planOptions': [
{'option': 'A', 'values': ['1', '2', '3', '4', '5']},
{'option': 'B', 'values': ['1', '2', '3', '4', '5']},
{'option': 'C', 'values': ['1', '2', '3', '4', '5']}
]
};
return (
<div>
<PricingPlanTable table={pricingPlans}/>
</div>
);
}
}
PricingPlanTable.jsx
import React, { PropTypes, Component } from 'react';
export default class PricingPlanTable extends React.Component {
render() {
const table = this.props.table.map((table, i) => {
return (
<div key={i}>
<table>
<tbody>
<tr>
<th></th>
<th>Starter</th>
<th>Bronze</th>
<th>Silver</th>
<th>Gold</th>
<th>Enterprise</th>
</tr>
<tr>
<td></td>
<td>free</td>
<td>19€ /mo</td>
<td>79€ /mo</td>
<td>190€ /mo</td>
<td>custom</td>
</tr>
</tbody>
</table>
</div>
)})
return (
<div>
{table}
</div>
);
}
}
This is a mockup of what I am trying to achieve:
The PricingPlanTable.jsx has the table hardcoded but I am trying to use the 'this.props' functionality of React to iterate through it. I would like to use a skeleton of the template and populate it with the pricingPlans var from the BillingAccount.jsx file.
pricingPlans that you are passing as a prop is an object and cannot be iterated over. You would need to access each object within pricing plans since they actually contain an array and iterate over them.
Please look at the following documenatation on how to use Array.map() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
So with your current data structure you could do something like the following :
createHeaders() {
this.props.table.planNames.map((plan) => {
return <th>{plan}</th>
});
}
createContent() {
this.props.table.planPrices.map((price) => {
return <tr>{price}</tr>
});
}
render() {
const table = this.props.table;
return(
<table>
<tr>
{this.createHeaders}
</tr>
<tr>
{this.createContent}
</tr>
</table>
)
}
At first you should use an array with map.Use map in planOptions instead. Secondly in map you are returning the table again and again rather you must return only rows. This is what it should be like.
import React, { PropTypes, Component } from 'react';
export default class PricingPlanTable extends React.Component {
render() {
const table = this.props.table.planOptions.map((obj, i) => {
return (
<tr key={i}>
<td>{obj.option}</td>
{obj.value.map(value => {
return (
<td>{value}</td>
);
})}
</tr>
)})
return (
<div>
<table>
<tbody>
<tr>
<th></th>
<th>Starter</th>
<th>Bronze</th>
<th>Silver</th>
<th>Gold</th>
<th>Enterprise</th>
</tr>
<tr>
<td></td>
<td>free</td>
<td>19€ /mo</td>
<td>79€ /mo</td>
<td>190€ /mo</td>
<td>custom</td>
</tr>
{tbody}
</tbody>
</table>
</div>
);
}
}

Resources