I'm very new to React and I'm playing around with file uploading and reading the values.
I currently have an app where I want to upload a file (the file has different content every time, but the header info stays the same) and format the content, put it into a table and calculate some results.
The txt file contains several rows with information about cable types (Mx) and the length of cable necessary.
I'm trying to
isolate the content to get only rows with 'mx' content
split the content, so I can separate types of cable and lengths
calculate the cumulative length of all cables
There are 4 types (I think) and the format is unfortunately like this
2xM14+1xM10 225.67 0.00 0.00
The first part is types of cables and multiple needed (2xM14 means I have to double the lengths for the results)
The second part is length for each cable (if I have 2xM14 and 1xM10 I need 2xM14225.67 and 1xM10225.67)
The rest is not relevant.
import { Box, Button, TextField } from '#mui/material';
import React, { Component } from 'react';
import { useState, useEffect } from 'react';
import Table from '#mui/material/Table';
import TableBody from '#mui/material/TableBody';
import TableCell from '#mui/material/TableCell';
import TableContainer from '#mui/material/TableContainer';
import TableHead from '#mui/material/TableHead';
import TableRow from '#mui/material/TableRow';
import Paper from '#mui/material/Paper';
export default function Cable() {
const [text, setText] = useState('čekám na soubor');
const [lines, setLines] = useState([]);
const [newLines, setNewLines] = useState([]);
const [results, setResults] = useState(
[{ letters: [], numbers: [] }]
);
const typy = ['M7', 'M10', 'M14', 'M16'];
const [types, setTypes] = useState('');
const showFile = (e) => {
e.preventDefault();
const reader = new FileReader();
reader.onload = (e) => {
const text = e.target.result;
setText(text); // inserts doc
setLines(text.split('\n')) // split text into rows
console.log(lines);
};
reader.readAsText(e.target.files[0]);
};
// selects rows containing 'xM'
const splitLines = (e) => {
setLines(lines.filter(line => line.includes('xM')))
console.log(lines)
}
const splitArr = () => {
const result = lines.reduce((a, c) => {
const [letters, numbers] = c.split(/[ ]+/);
a.push({ letters, numbers });
return a;
}, []);
setResults(() => [...result]);
// setTypes((result.letters).replace(/[x||+]/g, ' '))
console.log(results);
// console.log(types);
};
return (
<Box>
<input type="file" onChange={showFile} />
<TextField
label='gde soubor?'
variant='outlined'
value={text}
fullWidth
disabled
multiline
rows={12}
>{types}</TextField>
<Button onClick={splitLines}>Rozděl do typů - Mx</Button> <br />
<Button onClick={splitArr}>Vlož do tabulky - a vyber délku</Button> <br />
<TableContainer component={Paper} sx={{ minWidth: 650, marginBottom: 5, marginTop: 5}}>
<Table sx={{ minWidth: 650}} aria-label="simple table">
<TableHead>
<TableRow >
<TableCell>Typ</TableCell>
<TableCell>Délka</TableCell>
</TableRow>
</TableHead>
<TableBody >
{results.map((radky, index) => (
<TableRow key={index}>
<TableCell component="th" scope="row" sx={{ fontSize: 11, background: '#eeeeee' }}>
{radky.letters}
</TableCell>
<TableCell component="th" scope="row" sx={{ fontSize: 11, background: '#eeeeee' }}>
{radky.numbers.length > 0 && parseFloat(radky.numbers)}
</TableCell>
<TableCell component="th" scope="row" sx={{ fontSize: 11, background: '#eeeeee' }}>
{radky.letters.length > 0 && radky.letters.replace(/[x||+]/g, ' ')}
</TableCell>
<TableCell component="th" scope="row" sx={{ fontSize: 11, background: '#eeeeee' }}>
{radky.letters.length > 0 && radky.letters.replace(/[x||+]/g, ' ').split(' ') }
</TableCell>
<TableCell component="th" scope="row" sx={{ fontSize: 11, background: '#eeeeee' }}>
{radky.letters.length > 0 && radky.letters.replace(/'M10'/g, '*')}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
);
}
I also replicated the app on stackblitz(https://stackblitz.com/edit/react-f3zts7)
I'm not sure what should be the ideal way how to do this, any help would be greatly appreciated.
Related
I'm using Django and React to create YouTube clone.
And I have an admin panel where user can delete and edit his videos.
But the problem is that it showing my videos and other users videos.
How can make that the admin panel will show only my videos?
views.py Api Views
class AdminVideoDetail(generics.RetrieveAPIView):
permission_classes = [IsAuthenticated]
quesryset = Video.objects.all()
serializer_class = VideoSerializer
videos.js Videos in the admin panel
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Container from '#material-ui/core/Container';
import Link from '#material-ui/core/Link';
import Paper from '#material-ui/core/Paper';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableContainer from '#material-ui/core/TableContainer';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import DeleteForeverIcon from '#material-ui/icons/DeleteForever';
import EditIcon from '#material-ui/icons/Edit';
import Button from '#material-ui/core/Button';
const useStyles = makeStyles((theme) => ({
cardMedia: {
paddingTop: '56.25%', // 16:9
},
link: {
margin: theme.spacing(1, 1.5),
},
cardHeader: {
backgroundColor:
theme.palette.type === 'light'
? theme.palette.grey[200]
: theme.palette.grey[700],
},
videoTitle: {
fontSize: '16px',
textAlign: 'left',
},
videoText: {
display: 'flex',
justifyContent: 'left',
alignItems: 'baseline',
fontSize: '12px',
textAlign: 'left',
marginBottom: theme.spacing(2),
},
}));
const Videos = (props) => {
const { videos } = props;
const classes = useStyles();
if (!videos || videos.length === 0) return <Button href={'/admin/create'} variant="contained" color="primary">New Video</Button>;
return (
<React.Fragment>
<Container maxWidth="md" component="main">
<Paper className={classes.root}>
<TableContainer className={classes.container}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell>Id</TableCell>
<TableCell align="left">Title</TableCell>
<TableCell align="left">Action</TableCell>
</TableRow>
</TableHead>
<TableBody>
{videos.map((video) => {
return (
<TableRow>
<TableCell component="th" scope="row">
{video.id}
</TableCell>
<TableCell align="left">
<Link
color="textPrimary"
href={'/video/' + video.id}
className={classes.link}
>
{video.title}
</Link>
</TableCell>
<TableCell align="left">
<Link
color="textPrimary"
href={'/admin/edit/' + video.id}
className={classes.link}
>
<EditIcon></EditIcon>
</Link>
<Link
color="textPrimary"
href={'/admin/delete/' + video.id}
className={classes.link}
>
<DeleteForeverIcon></DeleteForeverIcon>
</Link>
</TableCell>
</TableRow>
);
})}
<TableRow>
<TableCell colSpan={4} align="right">
<Button
href={'/admin/create'}
variant="contained"
color="primary"
>
New Video
</Button>
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Paper>
</Container>
</React.Fragment>
);
};
export default Videos;
If you want to look at the whole project, here is github: https://github.com/PHILLyaHI/diplom-work
Create a python module named permissions.py
add these line of code
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
"""
def has_object_permission(self, request, view, obj):
# I check if the request is of type GET or OPTIONS
#I return true, that the use is able to access on this views
if request.method in permissions.SAFE_METHODS:
return True
return obj.owner == request.user
"""
Instance must have an attribute named `owner` or you can change owner with the name of your models fields `user = models.ForeignKey(UserModel, on_delete=models.casscade).
"""
After, go in your views.py module, add
class AdminVideoDetail(generics.RetrieveAPIView):
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
quesryset = Video.objects.all()
serializer_class = VideoSerializer
Only videos of owner will be fetch
Trying to use MUI table with Collapse to expand/collapse rows. However when using collapse, the the expanded rows are squashed into one cell. How can I align the expanded cells to the parent table cells in a material-ui table?
what i tried is on this link https://codesandbox.io/s/affectionate-leaf-lhb47z
CODE
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core/styles";
import Grid from "#material-ui/core/Grid";
import Card from "#material-ui/core/Card";
import CardHeader from "#material-ui/core/CardHeader";
import Table from "#material-ui/core/Table";
import TableBody from "#material-ui/core/TableBody";
import TableCell from "#material-ui/core/TableCell";
import TableHead from "#material-ui/core/TableHead";
import TableRow from "#material-ui/core/TableRow";
import Paper from "#material-ui/core/Paper";
import TableContainer from "#material-ui/core/TableContainer";
import IconButton from "#material-ui/core/IconButton";
import KeyboardArrowDownIcon from "#material-ui/icons/KeyboardArrowDown";
import KeyboardArrowUpIcon from "#material-ui/icons/KeyboardArrowUp";
const useStyles = makeStyles((theme) => ({
header: {
backgroundColor: "white",
color: "#546e7a",
justifyContent: "left",
padding: "10px 0px",
fontWeight: "bold"
},
content: {
padding: 0
},
status: {
marginRight: "5px"
},
actions: {
justifyContent: "flex-end"
},
summaryTable: {
width: "auto",
marginBottom: "10px",
pointerEvents: "none"
},
noBorder: {
border: "none"
},
denseCell: {
padding: "5px"
},
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
inputGroup: {
marginBottom: theme.spacing(1)
}
}));
const data1 = [
{
amount: 400.0,
dr_cr: "dr",
ledgerName: "Furniture"
},
{
amount: 10,
dr_cr: "dr",
ledgerName: "chocolate"
},
{
amount: 100.0,
dr_cr: "dr",
ledgerName: "goods purchase"
}
];
const data = [
{
amount: 510.0,
dr_cr: "dr",
ledgerName: "Assets"
},
{
amount: 5,
dr_cr: "cr",
ledgerName: "Liability"
}
];
const ExpandableTableRow = ({ children, expandComponent, ...otherProps }) => {
const [isExpanded, setIsExpanded] = React.useState(false);
return (
<>
<TableRow {...otherProps}>
<TableCell padding="checkbox">
<IconButton onClick={() => setIsExpanded(!isExpanded)}>
{isExpanded ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
{children}
</TableRow>
{isExpanded && (
<TableRow>
<TableCell/>
{expandComponent}
</TableRow>
)}
</>
);
};
export default function App() {
const classes = useStyles();
const [records, setRecords] = useState(data || []);
const [records1, setRecords1] = useState(data1 || []);
return (
<div className="App">
<Grid item lg={12} md={12} xs={12}>
<Card>
<CardHeader
className={classes.header}
title={"Report"}
classes={{
title: classes.header
}}
/>
<Table stickyHeader>
<TableHead>
<TableRow>
<TableCell />
<TableCell>LedgerName</TableCell>
<TableCell>Debit</TableCell>
<TableCell>Credit</TableCell>
</TableRow>
</TableHead>
<TableBody>
{records.map((item) => (
<ExpandableTableRow
key={item.ledgerName}
expandComponent={
<Table>
<TableBody>
{records1.map((i) => (
<TableRow>
<TableCell>{i.ledgerName}</TableCell>
<TableCell>
{i.dr_cr === "dr" ? Math.round(i.amount, 2) : 0}
</TableCell>
<TableCell>
{i.dr_cr === "cr" ? Math.round(i.amount, 2) : 0}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
}
>
<TableCell>{item.ledgerName}</TableCell>
<TableCell>
{item.dr_cr === "dr" ? Math.round(item.amount, 2) : 0}
</TableCell>
<TableCell>
{item.dr_cr === "cr" ? Math.round(item.amount, 2) : 0}
</TableCell>
</ExpandableTableRow>
))}
</TableBody>
</Table>
</Card>
</Grid>
</div>
);
}
I have problems about Material UI table.
I searched Material UI table document which is https://material-ui.com/components/tables/.
I wanna know how to apply pagenation with my Jscode "CheckListComponent.js" like "Custom pagination actions" in that documents.
I just changed createData which is in that document to my Jsondata.
Now I'm confusing this Error
CustomPaginationActionsTable
C:/workspace/spring-backend-3/frontend/src/component/PagenationTableComponent.js:117
114 | return (
115 | <TableContainer component={Paper}>
116 | <Table className={classes.table} aria-label="custom pagination table">
> 117 | <TableBody>
| ^ 118 | {(rowsPerPage > 0
119 | ? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
120 | : rows
View compiled
I understand that means but I don't understand where I should fix.
Please tell me how to fix. In Japan, No one tell me how to fix now.
CheckList.js
import axios from 'axios'
const CHECKLIST_REST_API_URL = 'http://localhost:8080/api/users';
class CheckListService {
getList() {
return axios.get(CHECKLIST_REST_API_URL);
}
}
export default new CheckListService();
PagenationTableComponent.js
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles, useTheme } from '#material-ui/core/styles';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableContainer from '#material-ui/core/TableContainer';
import TableFooter from '#material-ui/core/TableFooter';
import TablePagination from '#material-ui/core/TablePagination';
import TableRow from '#material-ui/core/TableRow';
import Paper from '#material-ui/core/Paper';
import IconButton from '#material-ui/core/IconButton';
import FirstPageIcon from '#material-ui/icons/FirstPage';
import KeyboardArrowLeft from '#material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '#material-ui/icons/KeyboardArrowRight';
import LastPageIcon from '#material-ui/icons/LastPage';
import CheckListService from '../services/CheckList';
const useStyles1 = makeStyles((theme) => ({
root: {
flexShrink: 0,
marginLeft: theme.spacing(2.5),
},
}));
function TablePaginationActions(props) {
const classes = useStyles1();
const theme = useTheme();
const { count, page, rowsPerPage, onChangePage } = props;
const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0);
};
const handleBackButtonClick = (event) => {
onChangePage(event, page - 1);
};
const handleNextButtonClick = (event) => {
onChangePage(event, page + 1);
};
const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
};
return (
<div className={classes.root}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
>
{theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
{theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
</IconButton>
<IconButton
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
{theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
</IconButton>
<IconButton
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
{theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</div>
);
}
TablePaginationActions.propTypes = {
count: PropTypes.number.isRequired,
onChangePage: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
rowsPerPage: PropTypes.number.isRequired,
};
let rows = [];
rows = CheckListService.getList().then((response) => {
return response.data
});
const useStyles2 = makeStyles({
table: {
minWidth: 500,
},
});
export default function CustomPaginationActionsTable() {
const classes = useStyles2();
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="custom pagination table">
<TableBody>
{(rowsPerPage > 0
? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: rows
).map((row) => (
<TableRow key={row.listNo}>
<TableCell component="th" scope="row">
{row.listNo}
</TableCell>
<TableCell style={{ width: 160 }} align="right">
{row.saiyouDate}
</TableCell>
<TableCell style={{ width: 160 }} align="right">
{row.softwareName}
</TableCell>
</TableRow>
))}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={[5, 10, 25, { label: 'All', value: -1 }]}
colSpan={3}
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
SelectProps={{
inputProps: { 'aria-label': 'rows per page' },
native: true,
}}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
);
}
PostScript: I wrote a code as mentioned as described below.
then I got new error 'useEffect' is not defined in console.
So I import "import { useState } from 'react';" but dosen't fix.
What should I do to compile?
export default function CustomPaginationActionsTable() {
const classes = useStyles2();
const [page, setPage] = React.useState(0);
const [rows, setRows] = React.useState([]);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
useEffect(() => {
CheckListService.getList().then((response) => setRows(response.data)); // you may need to check if response.data returns an array, otherwise you will face errors.
}, [])
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="custom pagination table">
<TableBody>
{(rowsPerPage > 0
? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: rows
).map((row) => (
<TableRow key={row.listNo}>
<TableCell component="th" scope="row">
{row.listNo}
</TableCell>
<TableCell style={{ width: 160 }} align="right">
{row.saiyouDate}
</TableCell>
<TableCell style={{ width: 160 }} align="right">
{row.softwareName}
</TableCell>
</TableRow>
))}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={[5, 10, 25, { label: 'All', value: -1 }]}
colSpan={3}
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
SelectProps={{
inputProps: { 'aria-label': 'rows per page' },
native: true,
}}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
);
}
welcome sy-torii. you need remove the row variable outside from your function. instead, include at your CustomPaginationActionsTable a row state. then use useEffect to fetch your rows on component mount.
import React, { useEffect } from 'react'; // import useEffect
export default function CustomPaginationActionsTable() {
const classes = useStyles2();
const [page, setPage] = React.useState(0);
const [rows, setRows] = React.useState([]);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
useEffect(() => {
CheckListService.getList().then((response) => setRows(response.data)); // you may need to check if response.data returns an array, otherwise you will face errors.
}, []) // passing an empty array will call this function only at component mount
I am getting the following error:
Error: Maximum update depth exceeded.
With this component:
const UsersPage: React.FunctionComponent<UsersPageProps> = ({
location,
history,
match,
}): JSX.Element => {
const dispatch = useDispatch();
const { search } = location;
const query = parseInt(location.search, 10);
const [currentPage, setCurrentPage] = useState<number>(
isNaN(query) || query < 0 ? 0 : query
);
const users = useSelector((state: any) => state.manageUsers.users.results);
const isLoading = useSelector((state: any) => state.manageUsers.usersLoaded);
const totalPages = useSelector(
(state: any) => state.manageUsers.users.totalPages
);
const handlePaginationChange = (
event: React.ChangeEvent<any>,
pageNumber: number
): void => {
history.push(`${match.path}?page=${pageNumber ?? 0}`);
setCurrentPage(pageNumber ?? 0);
};
const handleAddUserOnClick = () =>
dispatch(manageUsersSetNewUserAndNavigate());
const handleEditOnClick = (id) =>
dispatch(manageUsersSetActiveEditUserAndNavigate(id));
useEffect(() => {
dispatch(manageUsersLoadUsers(currentPage));
}, [currentPage]);
return (
<section className="users page">
{!isLoading && <SectionLoaderWithMessage message={"Loading users..."} />}
{isLoading && (
<React.Fragment>
<Toolbar disableGutters={true}>
<Title flex={1}>Manage Users</Title>
<Button
variant="contained"
color="secondary"
onClick={handleAddUserOnClick}
startIcon={<AddCircle />}
>
Add User
</Button>
</Toolbar>
<TableContainer component={Paper}>
<Table aria-label="table">
<TableHead>
<TableRow style={{ backgroundColor: "white" }}>
<TableCell style={{ fontWeight: "bold", minWidth: 150 }}>
Email
</TableCell>
<TableCell style={{ fontWeight: "bold", minWidth: 150 }}>
Name
</TableCell>
<TableCell style={{ fontWeight: "bold", minWidth: 150 }}>
Surname
</TableCell>
<TableCell style={{ fontWeight: "bold", minWidth: 150 }}>
Firm
</TableCell>
<TableCell style={{ fontWeight: "bold", minWidth: 150 }}>
Type
</TableCell>
<TableCell style={{ fontWeight: "bold", minWidth: 150 }}>
Enabled
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.map((user, index) => (
<TableRow
key={`${user.id}-${index}`}
onClick={() => handleEditOnClick(user.id)}
hover
>
<TableCell>{user.email}</TableCell>
<TableCell>{user.name}</TableCell>
<TableCell>{user.surname}</TableCell>
<TableCell>{user.firmName}</TableCell>
<TableCell>{user.type}</TableCell>
<TableCell>{`${user.enabled}`}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
<ThemedTablePagination
totalPages={totalPages}
pageNumber={currentPage}
onChange={handlePaginationChange}
/>
</TableContainer>
</React.Fragment>
)}
</section>
);
};
export default UsersPage;
I do not see anywhere in the render that is updating the state to cause an infinite loop.
The function handlePaginationChange should be inside useEffect.
Currently each time setCurrentPage is called it re-render the component which in-turn calls the handlePaginationChange function again, hence calling setCurrentPage again and the cycle goes on and on.
I'd be grateful if you could help me with my problem.
I've written a component to demonstrate the information of an array which includes both index.js and TableData.js files.Transferring the information of array from index.js to TableData in order to demonstrating them.
I passed the arguments to event handler correctly but I get an error. What's the problem with my code? In which part have I made a mistake?
App.js
import React, {Component, Fragment} from 'react';
import {TableData} from './Layouts'
class App extends Component {
state = {
productList: [
{id: 11, name: 'CD', price: '2000', describe: 'Educational'},
{id: 24, name: 'Pen', price: '3500', describe: 'Design'},
{id: 83, name: 'Pencil', price: '2500', describe: 'Design'}
],
};
handleDeleteByIndex = index => {
const product = this.state.productList;
product.splice(index, 1);
this.setState({productList: product});
};
render() {
const {productList} = this.state;
return (
<Fragment>
<TableData rows={productList} onDeleteRow={this.handleDeleteByIndex}/>
</Fragment>
);
}
}
export default App
TableData.js
import React from 'react';
import {makeStyles} from '#material-ui/core/styles';
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Paper
} from '#material-ui/core';
//****** Style CSS ******
const useStyles = makeStyles({
root: {
width: '100%',
overflowX: 'auto'
},
table: {
minWidth: 650
}
});
const test = 'right';
const TableData= (props) => {
const classes = useStyles();
return (
<Paper className={classes.root}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Name Product</TableCell>
<TableCell align="right">Price</TableCell>
<TableCell align="right">Describe</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.rows.map((item, index) => (
<TableRow key={item.id}>
<TableCell component="th" scope="row">
{item.name}
</TableCell>
<TableCell align={test} data={item.name}>{item.price}</TableCell>
<TableCell align="right">{item.describe}</TableCell>
<TableCell align="right">
<button onClick={() => props.handleDeleteByIndex(index)}>
DEL
</button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
);
};
export default TableData
You are calling a function that does not exist. The passed down function in props is called onDeleteRow, not handleDeleteByIndex.
Just change it into:
onClick={() => props.onDeleteRow(index)}