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

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.

Related

Delete single row in sqlite DB with react and express

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'})
}

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
);
}
}

Updating state in react using componentDidUpdate

I cannot get the state to update in my code
I am having an issue wiith my componentDidUpdate() which does not update the state of assignments after making an API call
when updating assignments. When I update the expiration date of a particular assignment in my list, it makes an API call to the server and returns
true if the response succeeds. The only way to see the update change in the state is to refresh the page. componentDidUpdate()
is stuck in an infinite loop, can anyone identify the underlining cause for this?
Thanks for any help
import * as React from 'react';
import './BundleAssignments.less';
import { IBundles, featureAccessApi, IAssignmentsByFirm, IBundleAssignment } from '#afi/tfs';
import { Loader } from '#afi/tfs';
export interface IOwnProps {}
export interface IOwnState {
loadingBundles: boolean,
loadingAssignments?: boolean,
loadingUpdate?: boolean,
bundles: IBundles[],
assignments: IAssignmentsByFirm[],
expirationDate: string,
bundleId?: number | undefined
}
export class BundleAssignments extends React.Component<IOwnProps, IOwnState> {
constructor(props: IOwnProps) {
super(props);
this.state = {
loadingBundles: true,
bundles: [],
assignments: [],
expirationDate: "",
bundleId: undefined
};
}
public componentDidMount() {
this.loadBundles();
}
public componentDidUpdate(prevProps: IOwnProps, prevState: IOwnState)
{
if (prevState.assignments !== this.state.assignments && this.state.bundleId !== undefined){
this.loadBundleAssignments(this.state.bundleId);
}
}
public render() {
return (
<div className="bundle-assignments">
<h1>Bundle assignments</h1>
{
this.state.loadingBundles ? <Loader /> :
<>
<select onChange={e => this.onChangeSelectedBundle(e)}>
<option value="">-- Select a Bundle --</option>
{
this.state.bundles.map(b =>
<option key={b.id} value={b.id}>{b.name}</option>
)
}
</select>
{
this.state.assignments != null && this.state.assignments.length > 0 ?
(this.state.loadingAssignments || this.state.loadingUpdate) ? <Loader /> :
<>
<h1>Assignments</h1>
<div className="download">
<a href={"https://localhost:44301/api/v2/admin/featureBundle/download/" + this.state.bundleId}>Download Excel</a>
</div>
<table className="assignmentsTable">
{
this.state.assignments.map(a =>
<tr key={a.firmRef}>
<th>
<span>{a.firmName}</span><br />
<a href={"admin/teams/firm/" + a.firmRef}>View teams</a>
</th>
<td>
{
<ul id="entites">
{
a.entities.map(e =>
<li key={e.entityRef}>
<span>{e.entityName}</span>
</li>
)
}
</ul>
}
</td>
<td>
{
a.entities.map(e =>
<form key={e.entityRef} onSubmit={(event) => this.handleSubmit(event, e.bundleAssignment.entityRef, e.bundleAssignment.bundleId, e.bundleAssignment.entityTypeId)}>
<input type="datetime-local" name="expirationDate" defaultValue={e.bundleAssignment.expirationDate} onChange={this.handleInputChange} />
<input type="submit" value="Update" />
</form>
)
}
</td>
</tr>
)
}
</table>
</>
: null
}
</>
}
</div>
)
}
private loadBundles = () => {
featureAccessApi.bundles()
.then(response => this.loadBundlesSuccess(response.bundles));
}
private loadBundlesSuccess = (bundles: IBundles[]) => {
this.setState({ ...this.state,
...{
loadingBundles: false,
bundles: bundles
}
})
}
private onChangeSelectedBundle = (e: React.ChangeEvent<HTMLSelectElement>) => {
const bundleId = Number(e.target.value);
this.setState({ ...this.state, ...{ loadingAssignments: true, bundleId: bundleId } })
this.loadBundleAssignments(bundleId);
}
private handleSubmit = (e: React.FormEvent, entityRef: number, bundleId: number, entityTypeId: number) => {
e.preventDefault();
this.setState({ ...this.state, ...{ loadingUpdate: true }})
this.updateBundleAssignment(entityRef, bundleId, entityTypeId);
}
private handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const target = e.target;
const value = target.value;
const name = target.name;
this.setState({ ...this.state,
...{
[name]: value
}
})
}
private updateBundleAssignment = (entityRef: number, bundleId: number, entityTypeId: number) => {
const request: IBundleAssignment = {
entityRef: entityRef,
bundleId: bundleId,
entityTypeId: entityTypeId,
expirationDate: this.state.expirationDate
};
featureAccessApi.updateBundleAssignment(request)
.then(response => this.bundleAssignmentUpdateSuccess());
}
private bundleAssignmentUpdateSuccess = () =>
this.setState({ ...this.state, ...{ loadingUpdate: false }})
private loadBundleAssignments = (bundleId: number) => {
featureAccessApi.bundleAssignments(bundleId)
.then(response => this.loadBundleAssignmentsSuccess(response.assignmentsByFirms));
}
private loadBundleAssignmentsSuccess = (bundleAssignments: IAssignmentsByFirm[]) => {
this.setState({ ...this.state,
...{
loadingAssignments: false,
assignments: bundleAssignments
}
})
}
}
Comparing arrays with !== will only compare the reference of the arrays and not their contents, so every time you update the assignment array, loadBundleAssignments will be run again.
console.log([1,2] !== [1,2])
You could instead use e.g. Lodash isEqual to check if all the elements in the arrays match each other.
public componentDidUpdate(prevProps: IOwnProps, prevState: IOwnState) {
if (
!_.isEqual(prevState.assignments, this.state.assignments) &&
this.state.bundleId !== undefined
) {
this.loadBundleAssignments(this.state.bundleId);
}
}

Reactjs not updating the new value of product_number

Reactjs not updating the new value of product_number. I knew that similar question has been asked but am having hard time trying to resolve this.
The Reactjs code below displays provisions records from the arrays.
Now I need to update and replace the value the product_number from 001 to 006.
To this effect, I have added an update button which fetch the product_number from the Axios Call.
My problem is that product_number is not updated with 006 when the button is clicked.
Here is the json response of Axios Call for product_number updates
product_number.json
[{"product_number":"006"}]
Here is the code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import axios from 'axios';
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
loading: false
};
}
componentDidMount() {
this.setState({
data: [
{"provision_id":"1","provision":"Milk","category":[{"category_id":"1","category_price":"100 USD","product":[{"product_id":"1","product_number":"001"}] }]}
],
});
}
// Get and update New Product number of Milk
handleNewProductNumber(prod_id) {
alert(prod_id);
const prod_data = {
prod_id: prod_id};
axios
.get("http://localhost/provision/product_number.json", { prod_data })
.then(response => {
const newData = this.state.data.map(store => {
//if (product.product_id !== prod_id) return product;
return {
...store,
product: store.product.map(
product => {
if (product.product_id !== prod_id) return product
return { ...product, product_number: response.data[0].product_number }
}
)
};
});
this.setState(state => ({
data: newData
}));
console.log(response.data[0].category_price);
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<span>
<label>
<ul>
{this.state.data.map((store) => {
return (
<div key={store.provision_id}>
<div><h1>Provision Store</h1> <br />
<b> Product: </b>{store.provision}
</div>
{store.category && store.category.map((cat) => {
return (
<div key={cat.category_id}>
<div><b>Prices:</b> {cat.category_price}
</div>
{cat.product && cat.product.map((prod) => <div key={prod.product_id}>
<b>Product Number:</b> #{prod.product_number}
<br />
<input
type="button"
value="Get & Update New Product Number"
onClick={() => this.handleNewProductNumber(prod.product_id)}
/>
</div>)}
</div>
)
})}
</div>
)
})}
</ul>
</label>
</span>
);
}
}
Updated Section using map function
return {
...store,
category: store.category.map(
product: store.product.map(
product => {
if (product.product_id !== prod_id) return product
return { ...product, product_number: response.data[0].product_number }
})
})
};
The problem is the same of the other question, you have an array of object, with inside another array of objects, in your state:
data: [
{
"provision_id": "1",
"provision": "Milk",
"category": [
{
"category_id": "1",
"category_price": "100 USD",
"product": [
{
"product_id": "1",
"product_number": "001"
}
]
}
]
}
]
To update the inner level, you have to traverse all the state tree:
return {
...store,
category: [{
...store.category,
product: [{
...store.category[0].product,
product_number: response.data[0].product_number
}]
}]
};
Edit after... well, your edit
Your updated piece of code isn't valid syntax:
return {
...store,
category: store.category.map(
product: store.product.map(
product => {
if (product.product_id !== prod_id) return product
return { ...product, product_number: response.data[0].product_number }
}
)
})
};
The first store.category.map call takes a function which will be called with a single category as an argument.
You have to spread the category prior to shadow the product property:
return {
...store,
category: store.category.map(
category => ({
...category,
product: category.product.map(
product => {
if (product.product_id !== prod_id) return product
return { ...product, product_number: response.data[0].product_number }
}
)
})
)
};

Resources