How to delete item seleted in table product - reactjs

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

Related

Deleting necessary data (with checkbox) in React

Need to delete the data that is highlighted by the checkbox. When I click on the checkbox, in all checkboxes the done becomes: true, then false and i can't remove the highlights. When the remove function is worked, only the first element is deleted. How can write a remove function.
import React from "react";
import { useState } from "react";
const App = () => {
const [user, setUser] = useState([
{id:1, name:"Peter", surname:"Robinson"},
{id:2, name:"Ann", surname:"Walker"},
{id:3, name:"James", surname:"Allen"},
])
const [check, setCheck] = useState({done: false})
const remove = () => {
if (check.done) {
}
}
return <>
<table className="table table-bordered">
<thead>
<tr>
{Object.keys(user[0]).map((elm,i) => {
return <td key={i}>
{elm.charAt(0).toUpperCase() + elm.slice(1)}
</td>
})}
</tr>
</thead>
<tbody>
{
user.map((elem, ind) => {
return <tr key={ind}>
<td>{elem.id}</td>
<td>{elem.name}</td>
<td>{elem.surname}</td>
<td>
<input type="checkbox" name="" id="" onChange={() => setCheck({done: check.done ? false : true})}/>
</td>
</tr>
})
}
</tbody>
</table>
<button className="btn btn-primary ms-2" onClick={() => remove()}>Delete selected</button>
</>
}
export default App;
Thank you.
You should handle the checked state for each user independently, then delete the ones with the checked flag at true:
import React from 'react';
import { useState } from 'react';
const App = () => {
const [user, setUser] = useState([
{ id: 1, name: "Peter", surname: "Robinson", checked: false },
{ id: 2, name: "Ann", surname: "Walker", checked: false },
{ id: 3, name: "James", surname: "Allen", checked: false }
]);
const toggleCheck = (id) => {
const checkedIdx = user.findIndex((u) => u.id === id);
if (checkedIdx === -1) return;
const updatedUser = [...user];
updatedUser[checkedIdx].checked = !updatedUser[checkedIdx].checked;
setUser(updatedUser);
};
const remove = () => {
setUser([...user].filter((u) => !u.checked));
};
return (
<>
<table className="table table-bordered">
<thead>
<tr>
{Object.keys(user[0]).map((elm, i) => {
return (
<td key={i}>{elm.charAt(0).toUpperCase() + elm.slice(1)}</td>
);
})}
</tr>
</thead>
<tbody>
{user.map((elem, ind) => {
return (
<tr key={elem.id}>
<td>{elem.id}</td>
<td>{elem.name}</td>
<td>{elem.surname}</td>
<td>
<input
type="checkbox"
name=""
id=""
onChange={() => toggleCheck(elem.id)}
value={elem.checked}
/>
</td>
</tr>
);
})}
</tbody>
</table>
<button className="btn btn-primary ms-2" onClick={() => remove()}>
Delete selected
</button>
</>
);
};
export default App;
Here is the code to a working sandbox.

Display a table in React using different components

I'm just starting to learn React and what I'm trying to do is to display a table. I'm doing it using 3 components: App.js, DisplayTable.js, and TableRows.js. The reason I'm doing it this way is that later on, I will need certain rows of the table to be displayed subject to different conditions. I don't get any error messages, but the table is not being displayed. This is my code:
App.js:
import Form from './components/Form'
import { useState } from 'react'
import TableDisplay from './components/TableDisplay'
const App = () => {
const [rows, setRows] = useState([
{
id:1,
description:'',
semester:'',
prefix:'ENG',
number:'368/371',
grade:'',
editing:''
},
{
id:2,
description:'',
semester:'',
prefix:'',
number:'',
grade:'',
editing:''
},
{
id:3,
description:'',
semester:'',
prefix:'',
number:'',
grade:'',
editing:''
},
])
return (
<div className="container">
<Form/>
<TableDisplay rows={rows}/>
</div>
);
}
export default App;
TableDisplay.js:
import TableRows from "./TableRows"
const TableDisplay = ({rows}) => {
return (
<>
{rows.map((row) => {
<TableRows key={row.id} row={row}/>
})}
</>
)
}
export default TableDisplay
TableRows.js:
import React from 'react'
const TableRows = ({row}) => {
return (
<div className="container">
<table className="table table-striped">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Description</th>
<th scope="col">Semester</th>
<th scope="col">Prefix</th>
<th scope="col">Number</th>
<th scope="col">Grade</th>
<th scope="col">Editing</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">{row.id}</th>
<td>{row.description}</td>
<td>{row.semester}</td>
<td>ENG</td>
<td>368/371</td>
<td>{row.grade}</td>
<td><button type="button" className="btn btn-warning">Edit</button></td>
</tr>
<tr>
<th scope="row">{row.id}</th>
<td>{row.description}</td>
<td>{row.semester}</td>
<td>ENG</td>
<td>368/371</td>
<td>{row.grade}</td>
<td><button type="button" className="btn btn-warning">Edit</button></td>
</tr>
<tr>
<th scope="row">{row.id}</th>
<td>{row.description}</td>
<td>{row.semester}</td>
<td>ENG</td>
<td>368/371</td>
<td>{row.grade}</td>
<td><button type="button" className="btn btn-warning">Edit</button></td>
</tr>
</tbody>
</table>
</div>
)
}
export default TableRows
You should remove bracket
const TableDisplay = ({ rows }) => {
return (
<>
{rows.map((row) => <TableRows key={row.id} row={row} />)}
</>
);
};
or add return
const TableDisplay = ({ rows }) => {
return (
<>
{rows.map((row) => {
return <TableRows key={row.id} row={row} />;
})}
</>
);
};

How to store values of selected checkboxes in array in React js?

I make table contain students names, and checkbox for every row in the table, I want so store the students names that checked in the (students) array. How can I do that?
const [data, setData] = useState([]);
const [students, setStudents] = useState([]);
useEffect(() => {
Axios
.get("http://localhost:3003/studentsnotinsections")
.then(result => setData(result.data));
}, []);
console.log(students)
return(
<div>
<table className="table" >
<thead className="thead-dark">
<tr>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{data.map((item, id) => {
return <tr key={id}>
<td>{item.FullName}</td>
<td><input type="checkbox" /></td>
</tr>
})}
</tbody>
</table>
</div>
)}
Did you try simply adding onclick function to your checkbox?
const Compon = () => {
const [data, setData] = useState([]);
const [students, setStudents] = useState([]);
useEffect(() => {
Axios
.get("http://localhost:3003/studentsnotinsections")
.then(result => setData(result.data));
}, []);
const addOrRemove = (name) => {
const newStudents = [...students];
const index = newStudents.indexOf(name);
if (index === -1) {
newStudents.push(name);
} else {
newStudents.splice(index, 1);
}
setStudents(newStudents);
console.log(students)
}
return(
<div>
<table className="table" >
<thead className="thead-dark">
<tr>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{data.map((item, id) => {
return <tr key={id}>
<td>{item.FullName}</td>
<td><input type="checkbox" onClick={() => addOrRemove(item.FullName)} /></td>
</tr>
})}
</tbody>
</table>
</div>
)
}
You could use onChange handler, it's more standard for input handling that onClick
import { useCallback, useState } from "react";
export default function App() {
const [data, setData] = useState([
{FullName: 'Alex'},
{FullName: 'Richard'}
]);
const [students, setStudents] = useState([]);
let toggleValue = useCallback((event, id) => {
if (event.target.checked) {
setStudents(value => [...value, id])
} else {
setStudents(value => value.filter(it => it !== id))
}
}, [setStudents])
console.log(students)
return(
<div>
<table className="table" >
<thead className="thead-dark">
<tr>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{data.map((item, id) => {
return <tr key={id}>
<td>{item.FullName}</td>
<td><input type="checkbox" onChange={(e) => toggleValue(e, id)} /></td>
</tr>
})}
</tbody>
</table>
</div>
)
}

No access to "this"

I'm working on a web-application using the MERN stack that displays a table of clients with their name, email, and phone number. I haven't implemented Redux quite yet, but I'm using 'uuid' to supplement data in the table until I can get the redux store set up. So far I have displaying the the list and adding a client to the list working fine, but I am having trouble with the pesky delete button.
This is the current ClientTable component
import React, { Component } from "react";
import { Table, Container, Button } from "reactstrap";
import { connect } from "react-redux";
import {
getClients,
addClient,
editClient,
deleteClient,
} from "../actions/clientActions";
import PropTypes from "prop-types";
const renderClient = (clients, index, id) => {
return (
<tr key={index}>
<td>
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={() => {
this.setState((state) => ({
clients: state.clients.filter((client) => client.id !== id),
}));
}}
>
×
</Button>
</td>
<td>{clients.name}</td>
<td>{clients.email}</td>
<td>{clients.number}</td>
</tr>
);
};
class ClientTable extends Component {
componentDidMount() {
this.props.getClients();
}
onDeleteClick = (id) => {
this.props.deleteClient(id);
};
render() {
const { clients } = this.props.client;
// const { clients } = this.state;
return (
<Container id="listContainer">
<Table
id="listTable"
className="table-striped table-bordered table-hover"
dark
>
<tr class="listRow">
<thead id="tableHeader">
<tr>
<th id="listActions">Actions</th>
<th id="listName">Name</th>
<th id="listEmail">Email</th>
<th id="listNumber">Number</th>
</tr>
</thead>
<tbody class="listRow">{clients.map(renderClient)}</tbody>
</tr>
</Table>
</Container>
);
}
}
ClientTable.propTypes = {
getClients: PropTypes.func.isRequired,
client: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
client: state.client,
});
export default connect(mapStateToProps, {
getClients,
deleteClient,
addClient,
})(ClientTable);
This is the bit of code that is causing me issues
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={() => {
this.setState((state) => ({
clients: state.clients.filter((client) => client.id !== id),
}));
}}
>
×
</Button>
When I click the "delete" button I keep getting TypeError: Cannot read property 'setState' of unedefined
I know the error is because of 'this' isn't bound to anything, but I'm uncertain how to bind it within an onClick event if that is even possible or what even to bind it to. I am just lost as to how to approach this problem. (I'm still quite new to React).
If anyone has any ideas it would be greatly appreciated!
move renderClient function to ClientTable, and use it as a method of this class.
class ClientTable extends Component {
componentDidMount() {
this.props.getClients();
}
renderClient = (clients, index) => {
return (
<tr key={index}>
<td>
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={() => this.onDeleteClient(clients.id)}
>
×
</Button>
</td>
<td>{clients.name}</td>
<td>{clients.email}</td>
<td>{clients.number}</td>
</tr>
);
};
onDeleteClick = (id) => {
this.props.deleteClient(id);
};
render() {
const { clients } = this.props.client;
// const { clients } = this.state;
return (
<Container id="listContainer">
<Table
id="listTable"
className="table-striped table-bordered table-hover"
dark
>
<tr class="listRow">
<thead id="tableHeader">
<tr>
<th id="listActions">Actions</th>
<th id="listName">Name</th>
<th id="listEmail">Email</th>
<th id="listNumber">Number</th>
</tr>
</thead>
<tbody class="listRow">{clients.map(this.renderClient)}</tbody>
</tr>
</Table>
</Container>
);
}
}

Remove table row using Hooks

I'm new to react and learning hooks. I found examples online that im converting to use hooks as practice but running into an issue with one. The example i'm converting, I can't figure out why the "Remove" button for function handleRemoveSpecificRow on the table row doesn't work. It should remove the the row. I'm stuck at this point. Any help appreciated.
Demo: https://codesandbox.io/s/zq185w2zkm
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Table, Button, Input } from "reactstrap";
function App() {
const [rows, setRows] = useState([{}]);
const handleChange = index => e => {
const { name, value } = e.target;
const rows = [...rows];
rows[index] = {
[name]: value
};
setRows(rows);
};
const handleAddRow = () => {
const item = {
column_1: "",
column_2: ""
};
setRows([...rows, item]);
};
const handleRemoveRow = () => {
setRows(rows.slice(0, -1));
};
const handleRemoveSpecificRow = index => () => {
const rows = [...rows];
rows.slice(index, 1);
setRows(rows);
};
return (
<div>
<Table>
<thead className="thead-light">
<tr>
<th>#</th>
<th>Column 1</th>
<th>Column 2</th>
<th />
</tr>
</thead>
<tbody>
{rows.map((item, index) => (
<tr id="addr" key={index}>
<td>{index}</td>
<td>
<Input
type="text"
name="name"
value={rows[index].column_1}
onChange={handleChange(index)}
/>
</td>
<td>
<Input
type="text"
name="mobile"
value={rows[index].column_2}
onChange={handleChange(index)}
/>
</td>
<td>
<Button
outline
color="danger"
onClick={handleRemoveSpecificRow(index)}
>
Remove
</Button>
</td>
</tr>
))}
</tbody>
</Table>
<Button onClick={handleAddRow}>Add Row</Button>
<Button color="danger" onClick={handleRemoveRow}>
Delete Row
</Button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I too had my fair share of doubts like this, focus towards array/object manipulation techniques. Always manipulate data in a controlled way using unique id, key, etc..
https://codesandbox.io/s/y2lqj9qnjz
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Table, Button, Input } from "reactstrap";
function App() {
const [rows, setRows] = useState([]);
const handleChange = item => e => {
const { name, value } = e.target;
// const rows = [...rows];
// rows[index] = {
// [name]: value
// };
let items = rows.map(row => {
if (row.id === item.id) {
row[name] = value;
}
return row;
});
setRows(items);
};
const handleAddRow = () => {
let item = {
id: rows.length + 1,
column_1: "",
column_2: ""
};
setRows([...rows, item]);
};
const handleRemoveRow = () => {
setRows(rows.slice(0, -1));
};
const handleRemoveSpecificRow = item => () => {
// const rows = [...rows];
// rows.splice(index, 1);
// setRows(rows);
let items = rows.filter(row => row.id != item.id);
setRows(items);
};
console.log(rows);
return (
<div>
{rows.length != 0 && (
<Table>
<thead className="thead-light">
<tr>
<th>#</th>
<th>Column 1</th>
<th>Column 2</th>
<th />
</tr>
</thead>
<tbody>
{rows.map((item, index) => (
<tr id="addr" key={index}>
<td>{item.id}</td>
<td>
<Input
type="text"
name="column_1"
value={item.column_1}
onChange={handleChange(item)}
/>
</td>
<td>
<Input
type="text"
name="column_2"
value={item.column_2}
onChange={handleChange(item)}
/>
</td>
<td>
<Button
outline
color="danger"
onClick={handleRemoveSpecificRow(item)}
>
Remove
</Button>
</td>
</tr>
))}
</tbody>
</Table>
)}
<Button onClick={handleAddRow}>Add Row</Button>
<Button color="danger" onClick={handleRemoveRow}>
Delete Row
</Button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/y2lqj9qnjz
I've updated the link above.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Table, Button, Input } from "reactstrap";
function App() {
const [rows, setRows] = useState([
{
id: 1,
column_1: "",
column_2: ""
}
]);
const handleChange = (item) => (e) => {
const { name, value } = e.target;
// const rows = [...rows];
// rows[index] = {
// [name]: value
// };
let items = rows.map((row) => {
if (row.id === item.id) {
row[name] = value;
}
return row;
});
setRows(items);
};
const handleAddRow = () => {
let item = {
id: rows[rows.length - 1].id + 1,
column_1: "",
column_2: ""
};
setRows([...rows, item]);
};
const handleRemoveRow = () => {
setRows(rows.slice(0, -1));
};
const handleRemoveSpecificRow = (item) => () => {
// const rows = [...rows];
// rows.splice(index, 1);
// setRows(rows);
let items = rows.filter((row) => row.id != item.id);
setRows(items);
};
return (
<div>
{rows.length != 0 && (
<Table>
<thead className="thead-light">
<tr>
<th>#</th>
<th>Column 1</th>
<th>Column 2</th>
<th />
</tr>
</thead>
<tbody>
{rows.map((item, index) => (
<tr id="addr" key={index}>
<td>{item.id}</td>
<td>
<Input
type="text"
name="column_1"
value={item.column_1}
onChange={handleChange(item)}
/>
</td>
<td>
<Input
type="text"
name="column_2"
value={item.column_2}
onChange={handleChange(item)}
/>
</td>
<td>
<Button
outline
color="danger"
onClick={handleRemoveSpecificRow(item)}
>
Remove
</Button>
</td>
</tr>
))}
</tbody>
</Table>
)}
<Button onClick={handleAddRow}>Add Row</Button>
<Button color="danger" onClick={handleRemoveRow}>
Delete Row
</Button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Resources