Delete single row in sqlite DB with react and express - reactjs

As the title said, im trying to delete a single user with a click on the button in the Table. But it deletes all users. So i think i have to map the single id´s to the button. But how?
This is my first CRUD App, so im not that experienced yet.
here is my React userTable component:
import React, { Component } from 'react'
const API_ENDPOINT = process.env.REACT_APP_API_ENDPOINT
class Userstable extends Component {
constructor(props) {
super(props)
this.state = {
users: [],
isLoading: false,
isError: false
}
}
async componentDidMount() {
this.setState({ isLoading: true })
const response = await fetch(`${API_ENDPOINT}/api/users`)
if (response.ok) {
const users = await response.json()
this.setState({ users, isLoading: false })
} else {
this.setState({ isError: true, isLoading: false })
}
}
render() {
const { users, isLoading, isError } = this.state
if (isLoading) {
return <div>Loading...</div>
}
if (isError) {
return <div>Error</div>
}
return users.length > 0
? (
<table className="table" id="tblData" >
<thead>
<tr>
<th style={{ borderTopLeftRadius: "4px" }}>ID</th>
<th>Name</th>
<th>email</th>
<th style={{ borderTopRightRadius: "4px" }}></th>
</tr>
</thead>
<tbody>
{this.renderTableRows()}
</tbody>
</table>
) : (
<div>
No users.
</div>
)
}
renderTableHeader = () => {
return Object.keys(this.state.users[0]).map(attr =>
<th key={attr} >
{attr}
</th>)
}
deleteTableRow = () => {
return this.state.users.map(user => {
return (
fetch(`${API_ENDPOINT}/api/users/${user.id}`, {method: 'DELETE'})
)
})
}
renderTableRows = () => {
return this.state.users.map(user => {
return (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.regname}</td>
<td>{user.regemail}</td>
<td className="delButton" onClick={this.deleteTableRow}>✕</td>
</tr>
)
})
}
}
export default Userstable
and here is my express Backend route:
router.delete("/users/:id", (req, res, next) => {
var sql = "DELETE FROM Users WHERE id = ?"
var params = [req.params.id]
db.run (sql, params, (err) => {
if (err) {
res.status(400).json({ "error": res.message })
return;
}
res.status(200)
res.json({ "answer": "success" })
return
});
});
thanks!

You can pass the id in onClick:
<td className="delButton" onClick={() => this.deleteTableRow(user.id)}>✕</td>
and send the request with the id:
deleteTableRow = (id) => {
fetch(`${API_ENDPOINT}/api/users/${id}`, {method: 'DELETE'})
}

Related

React - How to get an id and use it to delete

So in react I made a button to delete some data so I need to get teh car by id and remove it by using react js axios so the response I got is an empty array so can some one help me please.
Here is the code :
in service data file :
get(id) {
return http.get(`/get/${id}`);
}
delete(id) {
return http.delete(`/delete/${id}`);
}
Component.jsx
this.state = {
idCars: null,
carName: "",
carModel: "",
cars: [],
submitted: false
};
}
getCar(idCars) {
DataService.get(idCars)
.then(response => {
this.setState({
cars: response.data
});
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
componentDidMount() {
this.getCar(this.props.match.params.idCars);
this.retrieveCars()
}
deleteC() {
DataService.delete(this.state.cars.idCars)
.then(response => {
this.props.history.push('/Classement');
this.refreshList()
})
.catch(e => {
console.log(e);
});
}
render() {
const { cars } = this.state;
return (
<div ><tbody>
{
cars.map(data => (
<tr >
<th scope="row">{data.idCars}</th>
<td>{data.carName}</td>
<td>{data.carModel}</td>
<td>
<button className="btn btn-danger" onClick={this.deleteC}>
Remove
</button>
</td>
</tr>
))
}
And doesn't remove nothing, how can I fix this guys
At the moment your DeleteC function tries to read:
this.state.cars.idCars
But this.state.cars is an array so idCars is only defined for a given index such as in:
this.state.cars[0].idCars
What you could do is modify your onClick behavior for this:
onClick={() => deleteC(data.idCars)}
This way the deleteC function will be called with the idCars of the selected row.

Display mongoDB data in a table with most recent date at the top of list in ReactJS

I have built an application using MERN stack that displays a table of orders.
Currently, I am displaying my orders in a table with the most recent order at the bottom. How do I flip this round, so that the most recent order is displayed at the top? I would also like to only display orders from today's date.
I am using the following code to fetch my orders:
export const fetchOrders = () => (dispatch) => {
fetch("/api/orders")
.then((res) => res.json())
.then((data) => {
dispatch({ type: FETCH_ORDERS, payload: data });
});
};
and I am displaying the results of this using the following code:
class Orders extends Component {
componentDidMount() {
this.props.fetchOrders();
}
render() {
const { orders } = this.props;
console.log(orders);
return !orders ? (
<div>No Orders</div>
) : (
<div className="orders" key={orders._id}>
<h2>Orders</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>DATE</th>
<th>NAME</th>
<th>DEPARTMENT</th>
<th>ADDITIONAL INFO</th>
<th>ITEMS</th>
</tr>
</thead>
<tbody>
{orders.map((order) => (
<tr>
<td>{order._id}</td>
<td>{order.createdAt}</td>
<td>{order.name}</td>
<td>{order.department}</td>
<td>{order.additionalInfo}</td>
<td>
{order.cartItems.map((item) => (
<div>
{item.count} {" x "} {item.title}
</div>
))}
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}
export default connect(
(state) => ({
orders: state.order.orders,
}),
{
fetchOrders,
}
)(Orders);
My response data from my console.log on orders is:
You can sort the data before dispatching the result:
export const fetchOrders = () => (dispatch) => {
fetch("/api/orders")
.then((res) => res.json())
.then((data) => {
const sortedData = data.sort((a, b) => {
const dateAInMillis = (new Date(a.createdAt)).getTime();
const dateBInMillis = (new Date(b.createdAt)).getTime();
return dateBInMillis - dateAInMillis;
})
dispatch({ type: FETCH_ORDERS, payload: sortedData });
});
};
This really just comes down to your query. It should look something like
const orders = await Orders.find({
...,
createdAt: {
$gte: moment().tz(<the users timezone>).startOf('day')
}
}, {
sort: { createdAt: -1 }
})

TypeError: this.state.webOrders.map is not a function

Trying to display the api data in the pageload load in react. It worked fine if I comment the Api call and display from the testdata. Api is working fine and returning results, I was able to log the json to console. But its throwing the error TypeError: this.state.webOrders.map is not a function I tried searching through the forums and I added the isLoading flag, but didn't work.
Anybody has any suggestion or faced the similar issue please let us know. Pasted the whole component code below. I am very new to react, not sure if I am missing any core concepts and asking a dump question.
thanks,
import React, { Component } from 'react'
import axios from 'axios';
import 'bootstrap/dist/js/bootstrap.bundle.min';
import 'bootstrap/dist/css/bootstrap.min.css';
class WebOrderGrid extends Component {
constructor(props) {
super(props) //since we are extending class Table so we have to use super in order to override Component class constructor
this.state = { //state is by default an object
webOrders: [
{ customerAccount: 1, customerName: 'ABC', totalValue: 21, totalweight: .05, webOrderNum: '315689' },
{ customerAccount: 2, customerName: 'TBD', totalValue: 19, totalweight: .03, webOrderNum: '234569' },
{ customerAccount: 3, customerName: 'HHH', totalValue: 16, totalweight: .08, webOrderNum: '11111' },
{ customerAccount: 4, customerName: 'MMMM', totalValue: 25, totalweight: .04,webOrderNum: '8965638' }
],
isLoading : true
}
}
componentDidMount = () =>
{
console.log('componentDidMount');
this.FetchOrders();
}
FetchOrders () {
axios.get("https://localhost:44301/Orders", {
params:{ isRefresh :false }
}).then(result => {
if (result.status === 200) {
console.log('Success 200');
this.setState({webOrders:JSON.stringify(result.data), isLoading : false });
console.log(JSON.stringify(result.data));
/* this.setState({webOrders:JSON.stringify(result.data),loading:false }, function () {
console.log('state:' + this.state.webOrders);
}); */
} else {
console.log('not 200 response');
}
}).catch(e => {
console.log(e.JSON);
});
}
renderTableHeader() {
let header = Object.keys(this.state.webOrders[0])
return header.map((key, index) => {
return <th key={index}>{key.toUpperCase()}</th>
})
}
renderTableData() {
const { isLoading, webOrders } = this.state;
return this.props.map((order, index) => {
const { customerAccount, customerName, totalValue, totalweight, webOrderNum } = order //destructuring
return (
<tr scope="row" key={webOrderNum}>
<td scope="col">{customerAccount}</td>
<td scope="col">{customerName}</td>
<td scope="col">{totalValue}</td>
<td scope="col" >{totalweight}</td>
<td scope="col">{webOrderNum}</td>
</tr>
)
})
}
render() {
const { isLoading, webOrders } = this.state;
return (
<div>
<h1 id='title'>webOrders</h1>
<div className="table-responsive">
{!isLoading ?
(
<table id='SalesOrders' className='table table-striped'>
<tbody>
<tr scope="row">{this.renderTableHeader()}</tr>
{this.renderTableData(webOrders)}
</tbody>
</table>
): (
<p>Loading...</p>
)
}
</div>
</div>
)
}
}
export default WebOrderGrid;
Corrections could be seen here.
JSON.stringify converts your array into string. No need to stringify the result.
On renderTableData, instead of this.props.map use webOrders.map
// JSON.stringify converts your array into string.
this.setState({webOrders: result.data, isLoading : false });
renderTableData() {
const { isLoading, webOrders } = this.state;
// use webOrder here.
return webOrders.map((order, index) => {
const { customerAccount, customerName, totalValue, totalweight, webOrderNum } = order //destructuring
return (
<tr scope="row" key={webOrderNum}>
<td scope="col">{customerAccount}</td>
<td scope="col">{customerName}</td>
<td scope="col">{totalValue}</td>
<td scope="col" >{totalweight}</td>
<td scope="col">{webOrderNum}</td>
</tr>
)
})

I get an error when using reactjs useState

I am using reactjs. I am using the material-table to get the data with the editable table.
But I get an error like the picture, how can I fix this error?
I use useState for the edit settings of the table.
Please can you help with the error?
I do not receive any errors while receiving data. I just use editing on the table as active / inactive.
But
     const [, forceUpdate] = useState (false);
     const [data, setData] = useState (drBounty);
gives error for lines.
screenshot of the error and my source code below
import React, { Component, useState } from "react";
import withAuth from "../../components/helpers/withAuth";
import AlertMessageBox from "../../components/helpers/AlertMessageBox";
import { connect } from "react-redux";
import { Button, Col, Row, Table, Input } from "reactstrap";
import MaterialTable, { MTableEditRow } from "material-table";
import icons from '#material-ui/core/Icon';
import DeleteOutline from '#material-ui/icons/DeleteOutline';
import Edit from '#material-ui/icons/Edit';
class Bounty extends Component {
constructor(props) {
super(props);
this.state = {
isLoaded: true,
drBounty: [],
drList: [],
columns: [
{ title: 'Name', field: 'doctorName',
cellStyle:{padding: "1px", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "1px"},
editComponent: (props) => (
<Input
type="text"
placeholder={props.columnDef.title}
defaultValue={props.value}
onChange={(e) => props.onChange(
this.setState({
doctorName: e.target.value
})
)}
/>
)
},
{ title: 'LastName', field: 'doctorLastName',
cellStyle:{padding: "1px", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "5px"},
editComponent: (props) => (
<Input
type={"text"}
placeholder={"Doktor soyadı"}
defaultValue={props.value}
onChange={(e) => props.onChange(
this.setState({
doctorLastName: e.target.value
})
)}
/>
)
}
]
};
this.getBountyList = this.getBountyList.bind(this);
}
async componentDidMount() {
await fetch(
`${this.domain}/api/user/groupusers?groupCode=`+
this.props.account_profile.profile.profile.groupCode,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
}
}
)
.then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
console.log(json)
})
.catch(error => {
console.log(error)
return error;
});
}
async getBountyList(id) {
await fetch(`${this.domain}/api/bounty/list?groupCode=${this.props.account_profile.profile.profile.groupCode}&doctor=${id}`,{
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
}
})
.then(res => {
console.log(res);
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
console.log(json)
})
.catch(error => {
console.log(error);
return error;
});
}
render() {
const {isLoaded, drList, drBounty} = this.state;
const [, forceUpdate] = useState(false);
const [data, setData] = useState(drBounty);
const isRowUpdating = (rowData, status) => {
rowData.tableData.editing = status ? "update" : undefined;
forceUpdate(status);
};
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"animated fadeIn "}>
<Row>
<div> </div>
<Col sm={{span:1, offset:0.9}}>
<Table>
<thead>
<tr>
<th width={"20"} />
<th width={"50"}>Adı</th>
<th width={"70"}>Soyadı</th>
</tr>
</thead>
<tbody>
{
drList
.map(item => (
<tr key={item.id}>
<td>
<Button
block
outline
color="info"
onClick={() => this.getBountyList(item.id)}
>
Aç
</Button>
</td>
<td>{item.first_name} </td>
<td>{item.last_name}</td>
</tr>
))}
</tbody>
</Table>
</Col>
<MaterialTable
Icons={icons}
style={{height: "50", width: "50"}}
columns={ this.state.columns }
data={ this.state.drBounty }
actions={[
rowData => ({
icon: Edit,
tooltip: "Edit row",
onClick: (event, rowData) => {
isRowUpdating(rowData, true);
this.setState({
id: rowData.id,
user: rowData.user,
doctor: rowData.doctor,
doctorName: rowData.doctorName,
doctorLastName: rowData.doctorLastName,
totalBounty: rowData.totalBounty,
description: rowData.description,
customerName: rowData.customerName,
bountyDate: rowData.bountyDate,
createdDate: rowData.createdDate,
groupCode: rowData.groupCode
});
}
})
]}
components={{
EditRow: props => {
const newRowData = {
...drBounty, // *MUST INCLUDE tableData FROM ORIGINAL props.data!!*
id: "DEFAULT VALUES", // <-- // Set whatever default data you want here
doctorName: "ON EDIT" // <-- // (or pull from state, etc.. whatever you want)
};
return (
<MTableEditRow
{...props}
data={newRowData}
onEditingCanceled={(mode, rowData) => {
isRowUpdating(rowData, false);
}}
onEditingApproved={(mode, newData, oldRowData) => {
const dataCopy = [...drBounty];
const index = drBounty.indexOf(props.data);
dataCopy[index] = newData;
setData(dataCopy);
isRowUpdating(props.data, false);
}}
/>
);
}
}}
/>
</Row>
</div>
);
}
}
}
export default connect(withAuth( Bounty ));
You are trying to use the Hook (useState()) inside the render() method. Hooks can only be used inside of function components. However, you are using a class component so you have no need of this Hook.
Suggested Reading: https://reactjs.org/docs/hooks-state.html
Instead of using a Hook, you can use the following in your class component to accomplish the same results. Let's have a look :)
Initialize State in Constructor
this.state = { foo: bar };
You have already done this!
Update State with this.setState()
const [data, setData] = useState(drBounty);
Becomes ..
this.setState({data:drBounty});
However, you want to update the drBounty prop that you set up in the constructor, so you will want something more like this ..
this.setState({drBounty:someData})
Since that prop is an array, you will most likely want to spread (...) that data using the current array.
Re-Render without Updating State
As for your other implementation of useState() it appears you want to re-render without making any updates to state.
const [, forceUpdate] = useState(false);
However, instead you will want to simply use ...
this.render()

How to properly display JSON result in a table via ReactJS

I have this code which fetches data from an API and displays JSON response in a div. How do I display the JSON response in a table?
This is how I display it in div via status.jsx:
// some codings
render() {
const { status, isLocal } = this.props;
if(!isLocal()) {
return (
<div className="status">
<div className="status-text">
<b>Status</b> {status.text}<br />
<b>Title</b> status.textTitle} <br />
<b>Event</b> {status.textEvent}
</div>
</div>
)
}
}
I have tried displaying it in a table as per below but could not get it to be aligned properly
//some codings
render() {
const { status, isLocal } = this.props;
if(!isLocal()) {
return (
<table>
<tbody>
<th>Status</th>
<th>Title</th>
<th>Event</th>
<tr>
<td>{status.text} </td>
<td>{status.textTitle} </td>
<td>{status.textEvent}</td>
<td><button
className="btn btn-danger status-delete"
onClick={this.toggleDeleteConfirmation}
disabled={this.state.showDeleteConfirmation}
>
Delete
</button></td>
</tr></tbody>
</table>
)
}
}
Here is profile.jsx:
import React, { Component } from 'react';
import {
isSignInPending,
loadUserData,
Person,
getFile,
putFile,
lookupProfile
} from 'bs';
import Status from './Status.jsx';
const avatarFallbackImage = 'https://mysite/onename/avatar-placeholder.png';
const statusFileName = 'statuses.json';
export default class Profile extends Component {
constructor(props) {
super(props);
this.state = {
person: {
name() {
return 'Anonymous';
},
avatarUrl() {
return avatarFallbackImage;
},
},
username: "",
statuses: [],
statusIndex: 0,
isLoading: false
};
this.handleDelete = this.handleDelete.bind(this);
this.isLocal = this.isLocal.bind(this);
}
componentDidMount() {
this.fetchData()
}
handleDelete(id) {
const statuses = this.state.statuses.filter((status) => status.id !== id)
const options = { encrypt: false }
putFile(statusFileName, JSON.stringify(statuses), options)
.then(() => {
this.setState({
statuses
})
})
}
fetchData() {
if (this.isLocal()) {
this.setState({ isLoading: true })
const options = { decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/' }
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
person: new Person(loadUserData().profile),
username: loadUserData().username,
statusIndex: statuses.length,
statuses: statuses,
})
})
.finally(() => {
this.setState({ isLoading: false })
})
} else {
const username = this.props.match.params.username
this.setState({ isLoading: true })
lookupProfile(username)
.then((profile) => {
this.setState({
person: new Person(profile),
username: username
})
})
.catch((error) => {
console.log('could not resolve profile')
})
const options = { username: username, decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/'}
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
statusIndex: statuses.length,
statuses: statuses
})
})
.catch((error) => {
console.log('could not fetch statuses')
})
.finally(() => {
this.setState({ isLoading: false })
})
}
}
isLocal() {
return this.props.match.params.username ? false : true
}
render() {
const { handleSignOut } = this.props;
const { person } = this.state;
const { username } = this.state;
return (
!isSignInPending() && person ?
<div className="container">
<div className="row">
<div className="col-md-offset-3 col-md-6">
{this.isLocal() &&
<div className="new-status">
Hello
</div>
}
<div className="col-md-12 statuses">
{this.state.isLoading && <span>Loading...</span>}
{
this.state.statuses.map((status) => (
<Status
key={status.id}
status={status}
handleDelete={this.handleDelete}
isLocal={this.isLocal}
/>
))
}
</div>
</div>
</div>
</div> : null
);
}
}

Resources