Regular react table to MaterialTable - reactjs

How can I add data in my Material Table from an array?
I have the following table:
<table className="table">
<thead>
<tr>
<th>Text1</th>
<th>Text2</th>
<th>text3 Comb</th>
</tr>
</thead>
<tbody>
{arr.map((values, index) => {
const textComb = `${values.text1}, ${values.text2}`;
return (
<tr key={index}>
<td>{values.text1}</td>
<td>{values.text2}</td>
<td>{textComb}</td>
<td></td>
</tr>
)
})}
</tbody>
</table>
I have too many data, so I'm trying to use MaterialTable to have a search, sort, and pagination option.
<MaterialTable
columns={[
{title: 'Text1', field: 'text1'},
{title: 'Text2', field: 'text2'},
{title: 'Text3', field: 'text3'}
]}
data={
arr((values, index) => {
{
// I'm confused here
}
})
}
/>

try this-
const createData = item => ({
text1: item.text1,
text2: item.text2,
text3: `${item.text1}, ${item.text2}`
});
const data = arr.map(item => createData(item));
check demo here - https://codesandbox.io/s/material-table-example-5cohx?file=/src/App.js

Related

How can I filter and show an array with React?

I'm trying to filter some companies array -that is being shown in a table- using multiple checkboxes. These checkboxes returns an array of strings with some status. For example: ['accepted', 'pending', 'declined'];.
The problem is that while the checkboxes returns the status OK, I cannot manage to filter the companies array with the checkboxes data.
Here is my main code:
function App() {
const [filters, setFilters] = useState([]);
const [companies, setCompanies] = useState([
{ id: 1, status: "accepted", name: "001", date: "01/01/2022" },
{ id: 2, status: "accepted", name: "001", date: "01/01/2022" },
{ id: 8, status: "accepted", name: "001", date: "10/04/2022" },
]);
//HERE I TRY TO FILTER MY COMPANIES ARRAY WITH THE SELECTED CHECKBOXES
const showFilteredCompanies = (filters) => {
return [...companies].filter((company) => {
return filters.includes(company.status);
});
}
//Inside data I have my array of selected status like this: ['accepted', 'pending', 'declined']
const handleFilters = (data) => {
let newFilters = {...filters};
newFilters = data;
setFilters(newFilters);
// THIS CONSOLE.LOG SHOWS THE FILTERED ARRAY OF COMPANIES JUST FINE
console.log(showFilteredCompanies(newFilters));
const filtered = showFilteredCompanies(newFilters);
//BUT WHEN I TRY TO SAVE MY COMPANIES FILTERED ARRAY IN MY STATE THE FILTERING DOESN'T WORK AS IT SHOULD
console.log(filtered);
setCompanies(filtered);
}
return (
<div className="App">
<Checkbox
handleFilters={data => handleFilters(data)}
/>
{/* companies list */}
<div>
{companies.length ?
(
<table>
<thead>
<tr>
<th>ID</th>
<th>Estado</th>
<th>nombre</th>
<th>Fecha</th>
</tr>
</thead>
<tbody>
{companies.map((company, i) => (
<tr key={i}>
<td>{company.id}</td>
<td>{company.status}</td>
<td>{company.name}</td>
<td>{company.date}</td>
</tr>
)
)}
</tbody>
</table>
) : (
<h2>No hay compañías para mostrar</h2>
)
}
</div>
{/* list length */}
<div>
<h3>Cantidad de compañías: {companies.length}</h3>
</div>
</div>
);
}
export default App;
I was expecting to filter my companies array with all the strings of my checkboxes data array to show only the companies.status that matches the selected status of the checkboxes
It seems that the filtering of companies might not need to be another state, and could possibly be chained with map() in the output for simplicity.
Not sure if it would work without testing in the use case, but assuming that filters are updated just fine as posted, perhaps try omit showFilteredCompanies and setCompanies in handleFilters, and add in the output:
{ /* companies list with filter before map */ }
<div>
{companies.length ? (
<table>
<thead>
<tr>
<th>ID</th>
<th>Estado</th>
<th>nombre</th>
<th>Fecha</th>
</tr>
</thead>
<tbody>
{companies
.filter((company) =>
filters.length > 0 ? filters.includes(company.status) : true
)
.map((company, i) => (
<tr key={i}>
<td>{company.id}</td>
<td>{company.status}</td>
<td>{company.name}</td>
<td>{company.date}</td>
</tr>
))}
</tbody>
</table>
) : (
<h2>No hay compañías para mostrar</h2>
)}
</div>

How can I destructure my array of multiple objects

[
0: {_id: '61de38eb6ea1563609e1d0a7', title: 'FALCON SR SUNTOUR', price: '59', description: ' Alloy.., …}
1: {_id: '61d7a8b885c68311be8dd1b3', title: 'Lifelong LLBC2702 Falcon', price: '59', description: 'Low Maintenance: High.., …}
]
I am creating a react project. I have the above array of objects on my database. If any user place order the order list and user email will go into a single array. So my question is how can I display the orders. I have tried a map also tried a nested map but got " order.map is not a function". Here is the code
{orders.map((order, idx) => order.map(singleOrder => console.log(singleOrder)))}
I want to destructure the order details into UI
This is my code:
const ManageAllOrders = () => {
const [orders, setOrders] = useState([])
const { user } = UseAuth()
useEffect(() => {
fetch(`https://polar-savannah-40370.herokuapp.com/dashboard/orders`)
.then(res => res.json())
.then(data => setOrders(data))
}, [user.email])
console.log('orders', orders);
return (
<div>
<h2>Manage Orders</h2>
<Table responsive striped bordered hover size="sm">
<thead>
<tr>
<th>#</th>
<th>Product Name</th>
<th>Price</th>
<th>Email</th>
<th>Address</th>
<th>Order Date</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{
orders?.map((order, idx) =>
Object.defineProperties(order).map(([key, value]) => {
return (
<div>
{key} : {value}
</div>
);
})
)}
{/* {orders.map((order, idx) => order[0].map(console.log()))} */}
</tbody>
</Table>
</div>
);
};
export default ManageAllOrders;
You cannot call map on each order item as it is an object. To iterate over them use Object.entries method.
Try like below
{
orders?.map((order, idx) =>
Object.entries(order).map(
([key, { description, title, price, cartQuantity }]) => {
if (key !== "_id") {
return (
<tr>
<td>{key}</td>
<td>{title}</td>
<td>{price}</td>
<td>{cartQuantity}</td>
<td>{description}</td>
<td>email</td>
<td>address</td>
</tr>
);
}
}
)
);
}
I also noticed your array has stored values with string keys (email, _id). To retrieve them you can do it like below.
{orders?.["email"]}
{orders?.["_id"]}
Code Sandbox
Is Data type Array??
useEffect(() => {
fetch(`https://polar-savannah-40370.herokuapp.com/dashboard/orders`)
.then(res => res.json())
.then(data => setOrders(data))
}, [user.email])

How to delete item seleted in table product

I am trying to delete a product, but it's doesn't show success. I do not know how to get the id of that product to delete
My button onClick = {handleDelete} is import from component in other folder. I try to create handleDelete function, but I missing something in this case.
This is my code for that section
import React, { useState, useEffect } from "react";
import { Container, Row, Col, Table } from "react-bootstrap";
import Loading from "../../components/Loading";
import Button from "../../components/Button/index"
import firebaseApp from "../../api/config";
const ProductTableList = ({
products,
loading,
fetchProductRequest
}) => {
useEffect(() => {
fetchProductRequest();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const firebaseDb = firebaseApp.database();
const [currentId, setCurrentId] = useState("");
if (loading) {
return (
<Container>
<Row>
<Col>
<Loading />
</Col>
</Row>
</Container>
);
}
const handleDelete = (id) => {
const productId = firebaseDb.ref().push().key;
if (window.confirm("Are you sure to delete this record?")) {
firebaseDb
.ref("products")
.child(`products/${productId}`)
.remove((err) => {
if (err) console.log(err);
else setCurrentId("");
});
}
}
const handleUpdate = (event) => {
//TODO
}
return (
<Table striped bordered hover className="product-table">
<thead>
<tr>
<th>No.</th>
<th className="image">Image</th>
<th>Name</th>
<th>Category</th>
<th>Price</th>
<th>Description</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{!!products && products.length > 0 ? (
products.map((product, index) => {
return (
<tr key={index}>
<td>{index}</td>
<td>{product.image}</td>
<td>{product.name}</td>
<td>{product.category}</td>
<td>{product.price}</td>
<td>{product.description}</td>
<td>
<Button onClick={handleDelete} btnText="Delete" />
<Button onClick={handleUpdate} btnText="Update" />
</td>
</tr>
);
})
) :
(
<tr><td className="center-title">Product list is empty!</td></tr>
)}
</tbody>
</Table>
)
}
export default ProductTableList;
Can anyone help me? How do I delete the product that I have selected
Can anyone explain or support for me why? Thank you so much
I made a example, you need to add your function on button click and use your item id to be removed.
import React, { useState, useEffect } from "react";
import { Table } from "react-bootstrap";
const ProductTableList = () => {
const [currentId, setCurrentId] = useState("");
const [products, setProducts] = useState([{
image: 'image',
name: '01',
category: '01',
price: '01',
description: '01'
},
{
image: 'image',
name: '02',
category: '02',
price: '02',
description: '02'
},
{
image: 'image',
name: '03',
category: '03',
price: '03',
description: '03'
}])
const handleDelete = (id) => {
const removeItem = products.filter((item) => item !== products[id])
setProducts(removeItem)
}
return (
<Table striped bordered hover className="product-table">
<thead>
<tr>
<th>No.</th>
<th className="image">Image</th>
<th>Name</th>
<th>Category</th>
<th>Price</th>
<th>Description</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{!!products && products.length > 0 ? (
products.map((product, index) => {
return (
<tr key={index}>
<td>{index}</td>
<td>{product.image}</td>
<td>{product.name}</td>
<td>{product.category}</td>
<td>{product.price}</td>
<td>{product.description}</td>
<td>
<button onClick={() => handleDelete(index)}>Delete</button>
</td>
</tr>
);
})
) :
(
<tr><td className="center-title">Product list is empty!</td></tr>
)}
</tbody>
</Table>
)
}
export default ProductTableList;
Also, avoid index as element key
{ items.map((item, index) => (<li key={index}>{item}</li>)) }
When a list item was added or removed, and the key kept the same, the React assumed that the DOM element had not changed, and the app could not render.
An alternative to cases that the list doesn't have a unique ID is to generate one using shortID.
https://www.npmjs.com/package/shortid

React Typescript list mapped table row not rendering

I have a list of objects called items. I want to each object in the list to a row in the table. However, the rows are not being rendered. I'm using typescript with react-bootstrap. I'm wondering why this happened and how to fix it. Thanks!
Template.tsx
export default function Templates() {
const items = [
{
"name": "Item 1",
"alt": "First",
"description": "This is the first item"
},
{
"name": "Item 2",
"alt": "Second",
"description": "This is the second item"
},
{
"name": "Item 3",
"alt": "Third",
"description": "-"
}
]
return (
<>
<MyTable items={items}>MyTable</MyTable>
</>
)
}
MyTable.tsx
import React from 'react'
import { Table, Button } from 'react-bootstrap'
type TableProps = {
items: {
name: string,
alt: string,
description: string
}[]
}
const MyTable: React.FunctionComponent<TableProps> = ({
items
}) => {
return (
<>
<Table striped bordered hover variant="dark">
<thead>
<tr>
<th>Name</th>
<th>Alt</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{items.map(item => {
<tr>
<td>{item.name}</td>
<td>{item.alt}</td>
<td>{item.description}</td>
</tr>
})}
</tbody>
</Table>
</>
)
};
export default MyTable;
Right now only the thead are being rendered.
you are maping over the items and the map callback return undefined(no return statment),make sure to return the iterated item:
{items.map(item => {
return (
<tr key={item.name}>
<td>{item.name}</td>
<td>{item.alt}</td>
<td>{item.description}</td>
</tr>
)
})}
The problem is that you do not return anything here:
{items.map(item => {
<tr>
<td>{item.name}</td>
<td>{item.alt}</td>
<td>{item.description}</td>
</tr>
})}
In order for it to render something - you have to return.
Try this:
{items.map(item => <tr>
<td>{item.name}</td>
<td>{item.alt}</td>
<td>{item.description}</td>
</tr>)}
There is a problem with how you are using the arrow function inside items.map.
Note that there is a difference between the following:
item => { <tr></tr> }: this is a function with statement of <tr/><tr> defined in a block with no return statement.
item => (<tr></tr>): this is function which returns a single expression (<tr></tr>)
item => { return (<tr></tr>)}: this is a function with statement in a block with a return statement.
Since others have already answered, we can simplify it by replacing the curly braces and the return statement with parenthesis around the JSX you want to return
Ex:
{items.map(item => (
<tr key={item.name}>
<td>{item.name}</td>
<td>{item.alt}</td>
<td>{item.description}</td>
</tr>
)
)}
edit: what Soc said ^

REACT: Instead of sorting by clicking a button - sorting by clicking header "id" in table

I make request to server and I get response. Response it data which I display in view table-list. Also now I try implement when I click button changeAsc happen sort by asc-desc.
But I need that sort by asc-desc was happening when I click on header header id in table. And display the word asc or desc to the right of the header id. Table I export in file Home.js from file - Table.js.
What I need to change in file Table.js that implement sort when I click to header id?
Home.js:
import Table from "./Table/Table.js";
const Home = () => {
const [value, setValue] = useState({
listCategory: [],
sortAscDesc: "asc",
});
useEffect(() => {
async function fetchData(sortAscDesc) {
const res = await api('api/categories', sortAscDesc);
/....
}
fetchData(value.sortAscDesc);
}, [value.sortAscDesc]);
const changeSortAscDesc = () => {
setValue((prev) => ({
...prev,
sortAscDesc: prev.sortAscDesc == 'asc' ? 'desc' : 'asc'
}));
};
return (
<div>
<Table dataAttribute={value.listCategory}/>
// I WANT DELETE THIS BUTTON: - BECAUSE I WANT SORT BY HEADER "id"
<button onClick={() => changeSortAscDesc()}>changeAsc</button>
</div>
);
};
Table.js:
export default ({dataAttribute}) => (
<table className="table">
<thead className="table-head">
<tr>
<th>id</th> //I WANT SORT WHEN I CLICK ELEMENT id
<th>title</th>
<th>created_at</th>
</tr>
</thead>
<tbody>
{dataAttribute.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.title}</td>
<td>{item.created_at}</td>
</tr>
))}
</tbody>
</table>
);
You can try like this:
<Table dataAttribute={value.listCategory} changeSortAscDesc={changeSortAscDesc} />
In your Table.js
export default (props) => (
<table className="table">
<thead className="table-head">
<tr>
<th onClick={props.changeSortAscDesc}>id</th> //I want sort when I click by element id
<th>title</th>
<th>created_at</th>
</tr>
</thead>
<tbody>
{props.dataAttribute.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.title}</td>
<td>{item.created_at}</td>
</tr>
))}
</tbody>
</table>
);

Resources