I've written the following code:
const TableRow = ({row, i}) => (
<tr key={row.barcode}>
<td>{i}</td>
<td>{row.name}</td>
<td>{row.description}</td>
<td>{row.brand}</td>
<td>{row.barcode}</td>
</tr>
);
that is called in another component render() function that is
var table = (<Table striped bordered condensed hover>
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
{
this.state.products.map((row, i) =>
<TableRow row={row} id={i}/>
)
}
</tbody>
</Table>);
return table;
The problem is that in the rendered HTML all the <td> tags don't have any key property so
<tr>
<td></td>
<td>NAME</td>
<td>DESCR</td>
<td>NDARB</td>
<td>800800800</td>
</tr>
without any key property.
Keys help React identify which items have changed, are added, or are removed.
Keys are used internally and are never rendered in DOM. If you want to use it as an identifier, use id attribute in addition.
Ref: https://reactjs.org/docs/lists-and-keys.html#keys
That's because Key is a React property.
From the React docs:
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity
They are not rendered into the actual DOM, they are only used internally.
Related
I am trying to query my categories within my product. I created a table in which I want to see the categories of my product table. I am using Prisma as my typeORM and Apollo as a way to query my Postgres database. Please see the attached photo of my table. I have categories that are within my Product model.
Here is my query function using my UseQuery Hook from Apollo/Client.
const AllProductsQuery = gql`
query {
products {
id
name
description
img
price
ingredients
categories {
id
name
}
}
}
`
What I thought this would do was since I am querying the categories within the products I would be able to hit that information. However, it isn't even console logging that data.
This is what I have
<Table striped bordered hover >
<thead>
<tr>
<th>Product</th>
<th>Category</th>
<th>Price</th>
</tr>
</thead>
{data && data.products.map((product: Product, categories: Category) => {
return (
<tbody>
<tr>
<td>{product.name}</td>
<td>{product.categories.name}</td>
<td>{product.price}</td>
</tr>
</tbody>
)
})}
</Table>
However this doesn't even show the categories information within my products within the console log. The Product.name and Product.price work perfectly however, I try to run the same thing with product.categories.name doesn't work. Any information would be great!
In this code that you sent you're renaming product to Product in the data.products.map.
If you received categories from server, as I asked you in the comment, try this code
<Table striped bordered hover>
<thead>
<tr>
<th>Product</th>
<th>Category</th>
<th>Price</th>
</tr>
</thead>
{data &&
data.products.map((product) => {
return (
<tbody>
<tr>
<td>{product.name}</td>
<td>{product.categories.name}</td>
<td>{product.price}</td>
</tr>
</tbody>
);
})}
</Table>
I'm a newbie in development, so any help is welcome :)
Here's my Problem:
I'm using next.js - this might be important, because f.ex. document.createElement seem only work with useEffect.
I created a text area, where users add words separated with a comma (f.ex. "Nike, Adidas, New Balance"). I want to rewrite the existing code below, so that:
table is only visible/appears, when a user adds something in the inputbox
each word from the inputbox (f.ex. Nike, Adidas) creates a new row in the table (in table head "Brand").
By now, I was trying to use the .split and .forEach method to create a new Element(table). But I just can't make it work - maybe it's just not the right solution. Any help is welcome!
function Analyzer() {
const [brand, setBrand] = React.useState('');
const handleChange = (event) => {
setBrand(event.target.value.split(','))};
return(
<div>
<textarea type="text"
placeholder="Example:
Nike, Adidas, New Balance ..."
onChange={handleChange}></textarea>
<table className={styles.table}>
<thead>
<tr>
<th>No.</th>
<th>Brand</th>
<th>Also known as</th>
<th>Avg. price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>{brand}</td>
<td></td>
<td><input type= "number"></input>%</td>
</tr>
</tbody>
</table>
</div>);
}
Try something like the following. What I did was extract the Table component out and put any conditions for its rendering within it. You can even create a separate file for this component and pass any relevant props to it.
Secondly, I am putting the list of brands into state as brands within the handleChange function. This state variable is then iterated over using .map to render each row in the table.
function Analyzer() {
const [brands, setBrands] = React.useState([]);
const handleChange = ({ target }) => {
const { value } = target;
setBrands(value.split(','));
};
const Table = () => {
if (!brands || brands.length === 0) return null;
return (
<table className={styles.table}>
<thead>
<tr>
<th>No.</th>
<th>Brand</th>
<th>Also known as</th>
<th>Avg. price</th>
</tr>
</thead>
<tbody>
{brands.map((brand) => (
<tr>
<td>1</td>
<td>{brand}</td>
<td></td>
<td><input type= "number"></input>%</td>
</tr>
)}
</tbody>
</table>
);
};
return(
<div>
<input
onChange={handleChange}
placeholder="Example: Nike, Adidas, New Balance ..."
type="text"
value={brands}
/>
<Table />
</div>
);
};
Attempting to generate a table using ReactJS and within this table I want to have a unique key to identify each row (as recommended by ReactJS). The following code runs and generates the table I desire except with the following error:
Warning: 'Each child in an array or iterator should have a unique "key" prop'
Looking at my generated HTML the 'key' field indeed does not exist. I've also tried key={index} but it doesn't work either
export class Tablecontent extends Component{
constructor(props){
super(props);
this.state={
fileinfo:'null'
}
}
render(){
//const fileinfo = this.props.rows;
const fileinfo = ['myFile1.doc','myFile2.doc'];
var row='';
console.log("FILEINFO:"+fileinfo);
if(fileinfo=='null')
{
row ='';
}
else {
row = fileinfo.map((data,index) =>
<tr>
<td key="filename_{index}">{data}</td>
<td key="date_{index}">2/12/2017</td>
<td key="size_{index}">2.1 MB</td>
</tr>
);
}
return(
<div>
<table>
<tbody>
<tr>
<th>Name</th>
<th>Date Created</th>
<th>Size</th>
</tr>{row}</tbody>
</table>
</div>
);
}
}
Resulting HTML:
<table>
<tbody>
<tr><th>Name</th><th>Date Created</th><th>Size</th></tr>
<tr><td>myFile1.doc</td><td>2/12/2017</td><td>2.1 MB</td></tr>
<tr><td>myFile2.doc</td><td>2/12/2017</td><td>2.1 MB</td>
</tr>
</tbody>
</table>
It wants to see the key on the outer element returned in the map function as below. The key is for React's internal use and won't display in the html.
row = fileinfo.map((data,index) =>
<tr key={index}>
<td key="filename_{index}">{data}</td>
<td key="date_{index}">2/12/2017</td>
<td key="size_{index}">2.1 MB</td>
</tr>
);
I am using datatables to display table data. this table has an action column to remove record. I am trying the achieve the delete action by adding the event listener to the specific class. When i am trying to get the elements by the class name it is returning only first page elements of the datatable event though we have 5 pages. Can you help me in this regard.
var lastName = document.querySelectorAll('.lastname');
console.log(lastName);
i need the solution in plain javascript.
<table id="example" class="display nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger</td>
<td>Nixon</td>
<td><button class="btn btn-primary lastname" name="delete"></td>
</tr>
</table>
<script>
$(document).ready(function() {
$('#example').DataTable(
);
var lastName = document.querySelectorAll('.lastname');
console.log(lastName);// i am expecting this should return all elements with class **lastname**.
});
</script>
I have only included one row. assume we have 50 rows.
you can include the element like div
try this.
var lastName = document.querySelectorAll('div.lastname');
console.log(lastName);
you can read this Documentation for better information.
I'm new to using ReactJS and react-router. I want a clickable table row and something like the following setup:
<Link to=“#”>
<tr>
<td>{this.props.whatever1}</td>
<td>{this.props.whatever2}</td>
<td>{this.props.whatever3}</td>
</tr>
</Link>
but I know you can't put <a> tags between the <tbody> and <tr> tags. How else can I accomplish this?
PS: I prefer not to use jQuery if possible.
onClick works, but sometimes you need an actual <a> tag for various reasons:
Accessibility
Progressive enhancement (if script is throwing an error, links still work)
Ability to open a link in new tab
Ability to copy the link
Here's an example of a Td component that accepts to prop:
import React from 'react';
import { Link } from 'react-router-dom';
export default function Td({ children, to }) {
// Conditionally wrapping content into a link
const ContentTag = to ? Link : 'div';
return (
<td>
<ContentTag to={to}>{children}</ContentTag>
</td>
);
}
Then use the component like this:
const users = this.props.users.map((user) =>
<tr key={user.id}>
<Td to={`/users/${user.id}/edit`}>{user.name}</Td>
<Td to={`/users/${user.id}/edit`}>{user.email}</Td>
<Td to={`/users/${user.id}/edit`}>{user.username}</Td>
</tr>
);
Yes, you'll have to pass to prop multiple times, but at the same you have more control over the clickable areas and you may have other interactive elements in the table, like checkboxes.
Why don't you just use onClick?
var ReactTable = React.createClass({
handleClick: function(e) {
this.router.transitionTo('index');
},
render: function() {
return(
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Full Detail</th>
</tr>
</thead>
<tbody>
<tr onClick={this.handleClick.bind(this)}>
<td>{user.name}</td>
<td>{user.age}</td>
<td>{details}</td>
</tr>
</tbody>
</table>
</div>
);
}
});
This answers is based on #Igor Barbasin suggestion. This will add the link to the whole row instead of just the content and we also don't need to wrap all the individual 'td' element with 'Link'.
.table-row {
display: table-row
}
export default function Table() {
return (
<table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
{/* treats the link element as a table row element */}
<Link className="table-row">
<td>Noname</td>
</Link>
</tbody>
</table>
)
}
You can use useHistory() hook:
Declare:
const history = useHistory();
and use it with <tr> or <td> tag:
<tr onClick={() => history.push("/yoururl")}>
<td>{this.props.whatever1}</td>
<td>{this.props.whatever2}</td>
<td>{this.props.whatever3}</td>
</tr>
{shipment.assets.map((i, index) => (
<tr
style={{ cursor: "pointer" }}
onClick={(e) => e.preventDefault()}
>
<td>{index + 1}</td>
<td>{i._id}</td>
<td>{i.status}</td>
<td></td>
</tr>
))}