This question already has an answer here:
List elements not rendering in React [duplicate]
(1 answer)
Closed 23 days ago.
I have a react component that is supposed to take an array of items passed to the component as a prop and render a table. I have done this successfully with another component already. Yet for some reason, the table does not want to populate rows in this component.
Here is the component that renders the :
class OrderList extends React.Component {
constructor(props) {
super(props);
this.populateTable = this.populateTable.bind(this);
}
populateTable() {
return this.props.orders.map((order) => {
<tr key={order.id}>
<td>{order.orderNo}</td>
<td>{order.customer.name}</td>
<td>{order.customerPO}</td>
<td>{order.orderDate}</td>
<td>{order.shipDate}</td>
</tr>
});
}
render() {
return(
<Table striped bordered hover>
<thead>
<tr>
<td>Order No.</td>
<td>Customer Name</td>
<td>Customer P.O.</td>
<td>Order Date</td>
<td>Ship Date</td>
</tr>
</thead>
<tbody>
{this.populateTable()}
</tbody>
</Table>
);
}
}
Using react dev tools, I can see that the orders prop does contain the correct data, and array of objects. I can even throw in a console.log line within the forEach loop, so I know the component is actually looping over the data. However, no rows are rendered?
Your map is not returning anything this is the reason
class OrderList extends React.Component {
constructor(props) {
super(props);
this.populateTable = this.populateTable.bind(this);
}
populateTable() {
return this.props.orders.map((order) => (
<tr key={order.id}>
<td>{order.orderNo}</td>
<td>{order.customer.name}</td>
<td>{order.customerPO}</td>
<td>{order.orderDate}</td>
<td>{order.shipDate}</td>
</tr>
));
}
render() {
return(
<Table striped bordered hover>
<thead>
<tr>
<td>Order No.</td>
<td>Customer Name</td>
<td>Customer P.O.</td>
<td>Order Date</td>
<td>Ship Date</td>
</tr>
</thead>
<tbody>
{this.populateTable()}
</tbody>
</Table>
);
}
}
when you use curly braces in map you have to use return keyword to return anything
in order to return from your method you can try something like this
populateTable() {
return this.props.orders.map((order) => {
return (<tr key={order.id}>
<td>{order.orderNo}</td>
<td>{order.customer.name}</td>
<td>{order.customerPO}</td>
<td>{order.orderDate}</td>
<td>{order.shipDate}</td>
</tr>)
});
}
Related
Currently, I have a table class as follows:
import React from "react";
import "./Table.css";
export default function Table({theadData, tbodyData}) {
return (
<>
<table>
<tr>
<th></th>
<th>2017</th>
</tr>
{Array.from(theadData).forEach(heading => {
<tr>
<td class="largeHeader" key={heading}>{heading}</td>
<td class="primaryCell">{tbodyData[heading].value}</td>
</tr>;
})}
</table>
</>
);
}
When I add console.log(heading) or console.log(tbodyData[heading].value) within the loop, I can see that they give the expected values. However, none of the rows are added on. Why is that and how can I solve this problem? (I'd prefer to avoid jquery and libraries of that nature if possible, but am open to ideas.)
There are several mistakes you made:
change forEach to map
replace {} with (), or add return before <tr>
put key on the root element which is <tr>
{Array.from(theadData).map(heading => (
<tr key={heading}>
<td className="largeHeader">{heading}</td>
<td className="primaryCell">{tbodyData[heading].value}</td>
</tr>
))}
I'm having a problem wrapping my head around the .map() function as it relates to ReactJS. In practice, I have a table onto which I can add rows, but deleting a row by passing the index of the row is just not working. Here's what I have; can anyone clear up what I'm doing wrong?
import React from 'react';
import { render } from 'react-dom';
class CommentList extends React.Component {
constructor(props) {
super(props);
this.state = {
comments: []
};
this.handleCommentDelete = this.handleCommentDelete.bind(this);
}
handleCommentDelete(i) {
alert('i = ' + i);
let comments = [...this.state.comments];
comments.splice(i, 1);
this.setState({
comments: comments
});
}
render() {
return (
<table className="commentList">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
{
this.props.data.map((comment, i) => {
return (
<tr className="comment" key={i}>
<td className="commentId">{comment.Id}</td>
<td className="commentName">{comment.Name}</td>
<td className="commentPhone">{comment.Phone}</td>
<td className="commentEmail">{comment.Email}</td>
<td className="commentCRUD">
<a onClick={(i) => this.handleCommentDelete(i)}>
<i className="fa fa-trash" />
</a>
</td>
</tr>
);
})
}
</tbody>
</table>
);
}
}
export default CommentList;
Thanks in advance!
You are passing the index i, not the right way. Also i would prefer to pass id rather than index. Here is how you can do that:
import React from 'react';
import { render } from 'react-dom';
class CommentList extends React.Component {
constructor(props) {
super(props);
this.state = {
comments: []
};
this.handleCommentDelete = this.handleCommentDelete.bind(this);
}
handleCommentDelete(id) {
let comments = this.state.comments.filter(comment => comment.id !== id);
this.setState({
comments: comments
});
}
render() {
return (
<table className="commentList">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
{
this.props.data.map(comment => {
return (
<tr className="comment" key={comment.Id}>
<td className="commentId">{comment.Id}</td>
<td className="commentName">{comment.Name}</td>
<td className="commentPhone">{comment.Phone}</td>
<td className="commentEmail">{comment.Email}</td>
<td className="commentCRUD">
<a onClick={() => this.handleCommentDelete(comment.Id)}>
<i className="fa fa-trash" />
</a>
</td>
</tr>
);
})
}
</tbody>
</table>
);
}
}
export default CommentList;
Hope this works for you.
I'm unfamiliar with React and would appreciate some help. I have a table within a form where each row is a project that has a status (either 'Pending Approval' or 'Approved'). I also have a checkbox in each row. I would like it so that when the checkbox next to a row is selected and the form is submitted, I can change the status of each selected project to 'Approved.'
<Form>
<FormGroup>
<Button type="submit" onClick {this.submitClicked}>Approve Projects</Button>
</FormGroup>
<Table bordered={true}>
<thead>
<tr>
<th>Select</th>
<th>Project Name</th>
<th>Project Number</th>
<th>Project Status</th>
<th>Min Size</th>
<th>Max Size</th>
</tr>
</thead>
<tbody>
{projects.map((project: Project) =>
<tr key={project.projectNumber}>
<td>
<FormControl
type="checkbox"
id="selected"
value={project.projectName}
onChange={e => this.handleChange(e)}
/>
</td>
<td>{project.projectName}</td>
<td>{project.projectNumber}</td>
<td>{project.status}</td>
<td>{project.minSize}</td>
<td>{project.maxSize}</td>
</tr>
)}
</tbody>
</Table>
</Form>
What should go in my handleChange function and how should I go about doing this? I was wondering if there was some way to add the selected projects to an array and then change their status value?
You can use components with state. That allows you to manage a state inside a component. Thus you can manipulate it and change the projects' statuses in your example. More about this here: state classes
Example:
class YourComponent extends React.Component {
constructor(props) {
super(props);
this.state = {projects: props.projects};
}
handleChange = (e) => {
let projects = this.state.projects;
// manipulate your project here
this.setState({
projects: projects
});
}
render(){
return (<Form>
(...)
</Form>)
}
}
I cant display array object in map function. Could someone please tell me why ? When Im trying to display this object in the console I see it correctly.
class ProductsGrid extends React.Component {
constructor(props) {
super(props);
}
render() {
return (<Table striped bordered condensed hover>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Description</th>
<th>Url</th>
</tr>
</thead>
<tbody>
{this.props.products !== null ?
JSON.parse(this.props.products).map((product, index) => {
<tr>
{console.log(product.IdProduct)}
<td>{product.IdProduct}</td>
<td>{product.Name}</td>
<td>{product.Description}</td>
<td>{product.UrlFriendlyName}</td>
</tr>
}) : <tr><td></td><td></td><td></td><td></td></tr>}
</tbody>
</Table>);
}}
Your map function needs a return statement.
How can I get an HTML file from file system and parse specific elements from it.
For example, given the html snippet below, how can I extract the table content and render it?
<html>
<div>
<h1>header</h1>
<table id="a" border="1">
<th>Number</th>
<th>content A</th>
<th>contetn A</th>
<th>content A</th>
<tr>
<td>1</td>
<td>a</td>
<td>a</td>
<td>a</td>
</tr>
<th>Number</th>
<th>content B</th>
<th>content B</th>
<th>content B</th>
<tr>
<td>1</td>
<td>b</td>
<td>b</td>
<td>b</td>
</tr>
</table>
</div>
<br>
<footer>footer</footer>
</html>
Get html with fetch() and parse with react-native-html-parser, process and display with WebView.
import DOMParser from 'react-native-html-parser';
fetch('http://www.google.com').then((response) => {
const html = response.text();
const parser = new DOMParser.DOMParser();
const parsed = parser.parseFromString(html, 'text/html');
parsed.getElementsByAttribute('class', 'b');
});
P.S. fast-html-parser from other answers didn't work for me. I got multiple errors while installing it with react-native 0.54.
Just download HTML with fetch(), parse it using fast-html-parser, write result to state and render that state with WebView
I would recommend using this library: react-native-htmlviewer. It takes html and renders it as native views. You can also customize the way elements get rendered.
// only render the <table> nodes in your html
function renderNode(node, index, siblings, parent, defaultRenderer) {
if (node.name !== 'table'){
return (
<View key={index}>
{defaultRenderer(node.children, parent)}
</View>
)l
}
}
// your html
const htmlContent = `<html></html>`;
class App extends React.Component {
render() {
return (
<HTMLView value={htmlContent} renderNode={renderNode} />
);
}
}
I recommend this package react-native-render-html, is so famous and very simple for using